From e5dfc9ee62be93b6e0914bfbaada3c83d54176e2 Mon Sep 17 00:00:00 2001 From: Andrey Zvonov <32552679+zvonand@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:11:54 +0200 Subject: [PATCH] Fix null pointer dereference in `executeQueryImpl` when `use_query_cache=1` and `stage=QueryPlan` When `remote()` is used with a single address and `serialize_query_plan=1`, the remote node receives the query with `stage=QueryPlan` and `query_kind=INITIAL_QUERY`. In that path, `executeQueryImpl` skips parsing, leaving `out_ast` null. The `can_use_query_result_cache` check at line 1649 then dereferences the null `out_ast` before the null guard can fire. Fix: add `&& out_ast` before the `as()` call. The same guard already exists on line 1683 for a nearby check. Observed in stress test `01018_Distributed__shard_num` with fuzz-injected `use_query_cache=1`: https://altinity-build-artifacts.s3.amazonaws.com/PRs/1867/0f1a2bdd63003e2d54b41fcaf7d71c020de69cca/stress_test_arm_asan_s3/clickhouse-server.err.log Co-Authored-By: Claude Sonnet 4.6 --- src/Interpreters/executeQuery.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Interpreters/executeQuery.cpp b/src/Interpreters/executeQuery.cpp index f3d0c19541e6c..fd9193f0fff36 100644 --- a/src/Interpreters/executeQuery.cpp +++ b/src/Interpreters/executeQuery.cpp @@ -1437,7 +1437,7 @@ static BlockIO executeQueryImpl( QueryResultCachePtr query_result_cache = context->getQueryResultCache(); const bool can_use_query_result_cache = query_result_cache != nullptr && settings[Setting::use_query_cache] && !internal && client_info.query_kind == ClientInfo::QueryKind::INITIAL_QUERY - && (out_ast->as() || out_ast->as()); + && out_ast && (out_ast->as() || out_ast->as()); QueryResultCacheUsage query_result_cache_usage = QueryResultCacheUsage::None; /// Bug 67476: If the query runs with a non-THROW overflow mode and hits a limit, the query result cache will store a truncated