From e2e433bf18666fa9b6feb32e53b5ebd34b2c2cf2 Mon Sep 17 00:00:00 2001 From: roaldm153 Date: Mon, 27 Jul 2026 13:14:21 +0300 Subject: [PATCH 1/2] Fix segfault in ExplainNode() on a QE A receiving Motion has no child PlanState when its child slice runs on another gang. ExplainNode() recursed into it anyway and crashed. Return early when planstate is NULL. --- src/backend/commands/explain.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 0d63d374128..a25290efc25 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -1540,7 +1540,7 @@ ExplainNode(PlanState *planstate, List *ancestors, const char *relationship, const char *plan_name, ExplainState *es) { - Plan *plan = planstate->plan; + Plan *plan; PlanState *parentplanstate; ExecSlice *save_currentSlice = es->currentSlice; /* save */ const char *pname; /* node type name for text output */ @@ -1557,6 +1557,14 @@ ExplainNode(PlanState *planstate, List *ancestors, int motion_recv; int motion_snd; ExecSlice *parentSlice = NULL; + /* + * Guard if subtree on QE lives in another slice + * and not instantiated here. + */ + if (planstate == NULL) + return; + + plan = planstate->plan; /* Remember who called us. */ parentplanstate = es->parentPlanState; @@ -2945,8 +2953,11 @@ ExplainNode(PlanState *planstate, List *ancestors, /* lefttree */ if (outerPlan(plan) && !skip_outer) { - ExplainNode(outerPlanState(planstate), ancestors, - "Outer", NULL, es); + if (outerPlanState(planstate)) + { + ExplainNode(outerPlanState(planstate), ancestors, + "Outer", NULL, es); + } } else if (skip_outer) { From d3b5e844b71c21300742c5577f5022d1c3013ce4 Mon Sep 17 00:00:00 2001 From: Aleksey Rozhok Date: Mon, 27 Jul 2026 16:05:42 +0300 Subject: [PATCH 2/2] fix: comments grammar Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/backend/commands/explain.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index a25290efc25..9cfd09d5f7c 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -1557,13 +1557,12 @@ ExplainNode(PlanState *planstate, List *ancestors, int motion_recv; int motion_snd; ExecSlice *parentSlice = NULL; - /* - * Guard if subtree on QE lives in another slice - * and not instantiated here. - */ + /* + * Guard against the case where a subtree on the QE lives in another slice + * and is not instantiated in this slice. + */ if (planstate == NULL) return; - plan = planstate->plan; /* Remember who called us. */