Skip to content

Commit eaf0292

Browse files
committed
Fix unsafe memory management in CloneRowTriggersToPartition().
It's not really supported to call systable_getnext() in a different memory context than systable_beginscan() was called in, and it's *definitely* not safe to do so and then reset that context between calls. I'm not very clear on how this code survived CLOBBER_CACHE_ALWAYS testing ... but Alexander Lakhin found a case that would crash it pretty reliably. Per bug #15828. Fix, and backpatch to v11 where this code came in. Discussion: https://postgr.es/m/15828-f6ddd7df4852f473@postgresql.org
1 parent 05d36b6 commit eaf0292

File tree

1 file changed

+7
-7
lines changed

1 file changed

+7
-7
lines changed

src/backend/commands/tablecmds.c

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15772,8 +15772,7 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
1577215772
ScanKeyData key;
1577315773
SysScanDesc scan;
1577415774
HeapTuple tuple;
15775-
MemoryContext oldcxt,
15776-
perTupCxt;
15775+
MemoryContext perTupCxt;
1577715776

1577815777
ScanKeyInit(&key, Anum_pg_trigger_tgrelid, BTEqualStrategyNumber,
1577915778
F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(parent)));
@@ -15783,18 +15782,16 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
1578315782

1578415783
perTupCxt = AllocSetContextCreate(CurrentMemoryContext,
1578515784
"clone trig", ALLOCSET_SMALL_SIZES);
15786-
oldcxt = MemoryContextSwitchTo(perTupCxt);
1578715785

1578815786
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1578915787
{
15790-
Form_pg_trigger trigForm;
15788+
Form_pg_trigger trigForm = (Form_pg_trigger) GETSTRUCT(tuple);
1579115789
CreateTrigStmt *trigStmt;
1579215790
Node *qual = NULL;
1579315791
Datum value;
1579415792
bool isnull;
1579515793
List *cols = NIL;
15796-
15797-
trigForm = (Form_pg_trigger) GETSTRUCT(tuple);
15794+
MemoryContext oldcxt;
1579815795

1579915796
/*
1580015797
* Ignore statement-level triggers; those are not cloned.
@@ -15813,6 +15810,9 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
1581315810
elog(ERROR, "unexpected trigger \"%s\" found",
1581415811
NameStr(trigForm->tgname));
1581515812

15813+
/* Use short-lived context for CREATE TRIGGER */
15814+
oldcxt = MemoryContextSwitchTo(perTupCxt);
15815+
1581615816
/*
1581715817
* If there is a WHEN clause, generate a 'cooked' version of it that's
1581815818
* appropriate for the partition.
@@ -15876,10 +15876,10 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
1587615876
trigForm->tgfoid, trigForm->oid, qual,
1587715877
false, true);
1587815878

15879+
MemoryContextSwitchTo(oldcxt);
1587915880
MemoryContextReset(perTupCxt);
1588015881
}
1588115882

15882-
MemoryContextSwitchTo(oldcxt);
1588315883
MemoryContextDelete(perTupCxt);
1588415884

1588515885
systable_endscan(scan);

0 commit comments

Comments
 (0)