Skip to content

Commit 601084e

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 3c461d5 commit 601084e

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
@@ -15082,8 +15082,7 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
1508215082
ScanKeyData key;
1508315083
SysScanDesc scan;
1508415084
HeapTuple tuple;
15085-
MemoryContext oldcxt,
15086-
perTupCxt;
15085+
MemoryContext perTupCxt;
1508715086

1508815087
ScanKeyInit(&key, Anum_pg_trigger_tgrelid, BTEqualStrategyNumber,
1508915088
F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(parent)));
@@ -15093,18 +15092,16 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
1509315092

1509415093
perTupCxt = AllocSetContextCreate(CurrentMemoryContext,
1509515094
"clone trig", ALLOCSET_SMALL_SIZES);
15096-
oldcxt = MemoryContextSwitchTo(perTupCxt);
1509715095

1509815096
while (HeapTupleIsValid(tuple = systable_getnext(scan)))
1509915097
{
15100-
Form_pg_trigger trigForm;
15098+
Form_pg_trigger trigForm = (Form_pg_trigger) GETSTRUCT(tuple);
1510115099
CreateTrigStmt *trigStmt;
1510215100
Node *qual = NULL;
1510315101
Datum value;
1510415102
bool isnull;
1510515103
List *cols = NIL;
15106-
15107-
trigForm = (Form_pg_trigger) GETSTRUCT(tuple);
15104+
MemoryContext oldcxt;
1510815105

1510915106
/*
1511015107
* Ignore statement-level triggers; those are not cloned.
@@ -15123,6 +15120,9 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
1512315120
elog(ERROR, "unexpected trigger \"%s\" found",
1512415121
NameStr(trigForm->tgname));
1512515122

15123+
/* Use short-lived context for CREATE TRIGGER */
15124+
oldcxt = MemoryContextSwitchTo(perTupCxt);
15125+
1512615126
/*
1512715127
* If there is a WHEN clause, generate a 'cooked' version of it that's
1512815128
* appropriate for the partition.
@@ -15186,10 +15186,10 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
1518615186
trigForm->tgfoid, HeapTupleGetOid(tuple), qual,
1518715187
false, true);
1518815188

15189+
MemoryContextSwitchTo(oldcxt);
1518915190
MemoryContextReset(perTupCxt);
1519015191
}
1519115192

15192-
MemoryContextSwitchTo(oldcxt);
1519315193
MemoryContextDelete(perTupCxt);
1519415194

1519515195
systable_endscan(scan);

0 commit comments

Comments
 (0)