From 798d6df3efbed5dfb6c784aaeaf9982db113d487 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Mon, 16 Mar 2026 11:50:00 -0400 Subject: [PATCH 1/4] pg_plan_advice: Avoid a crash under GEQO. The previous code could allocate pgpa_sj_unique_rel objects in a context that had too short a lifespan. Fix by allocating them (and any associated List-related allocations) in the same context as the pgpa_planner_state to which they are attached. Reported-by: Alexander Lakhin Discussion: http://postgr.es/m/a6e6d603-e847-44dc-acd5-879fb4570062@gmail.com --- contrib/pg_plan_advice/pgpa_planner.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/contrib/pg_plan_advice/pgpa_planner.c b/contrib/pg_plan_advice/pgpa_planner.c index 5508b8af707..08e6ec199b9 100644 --- a/contrib/pg_plan_advice/pgpa_planner.c +++ b/contrib/pg_plan_advice/pgpa_planner.c @@ -90,6 +90,7 @@ typedef enum pgpa_jo_outcome typedef struct pgpa_planner_state { + MemoryContext mcxt; bool generate_advice_feedback; bool generate_advice_string; pgpa_trove *trove; @@ -324,10 +325,18 @@ pgpa_planner_setup(PlannerGlobal *glob, Query *parse, const char *query_string, * some purpose. That could be (1) recording that we will need to generate * an advice string, (2) storing a trove of supplied advice, or (3) * facilitating debugging cross-checks when asserts are enabled. + * + * Currently, the active memory context should be one that will last for + * the entire duration of query planning, but if GEQO is in use, it's + * possible that some of our callbacks may be invoked later with + * CurrentMemoryContext set to some shorter-lived context. So, record + * the context that should be used for allocations that need to live + * as long as the pgpa_planner_state itself. */ if (needs_pps) { pps = palloc0_object(pgpa_planner_state); + pps->mcxt = CurrentMemoryContext; pps->generate_advice_feedback = generate_advice_feedback; pps->generate_advice_string = generate_advice_string; pps->trove = trove; @@ -616,11 +625,15 @@ pgpa_join_path_setup(PlannerInfo *root, RelOptInfo *joinrel, /* If not a duplicate, append to the list. */ if (!found) { - pgpa_sj_unique_rel *ur = palloc_object(pgpa_sj_unique_rel); + pgpa_sj_unique_rel *ur; + MemoryContext oldcontext; + oldcontext = MemoryContextSwitchTo(pps->mcxt); + ur = palloc_object(pgpa_sj_unique_rel); ur->plan_name = root->plan_name; ur->relids = uniquerel->relids; pps->sj_unique_rels = lappend(pps->sj_unique_rels, ur); + MemoryContextSwitchTo(oldcontext); } } } -- 2.51.0