]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
pg_plan_advice: Avoid a crash under GEQO.
authorRobert Haas <rhaas@postgresql.org>
Tue, 17 Mar 2026 18:25:43 +0000 (14:25 -0400)
committerRobert Haas <rhaas@postgresql.org>
Tue, 17 Mar 2026 18:25:43 +0000 (14:25 -0400)
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. We also need to copy
uniquerel->relids, because the associated RelOptInfo may also be
allocated within a short-lived context.

Reported-by: Alexander Lakhin <exclusion@gmail.com>
Discussion: http://postgr.es/m/a6e6d603-e847-44dc-acd5-879fb4570062@gmail.com

contrib/pg_plan_advice/pgpa_planner.c

index c05d549dd1d4174d3f4f070efcec9759323d787b..fee88904760c6e4783eccdc7c7608cf706d866a9 100644 (file)
@@ -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;
+                               ur->relids = bms_copy(uniquerel->relids);
                                pps->sj_unique_rels = lappend(pps->sj_unique_rels, ur);
+                               MemoryContextSwitchTo(oldcontext);
                        }
                }
        }