diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2019-06-03 16:59:16 -0400 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2019-06-03 16:59:26 -0400 |
commit | eaf0292c3ba7acac2735f99a8988bd49a26112f5 (patch) | |
tree | cda7d40cd2c0bef2c692c7d400a36a2f0e8bebda /src | |
parent | 05d36b68ed011d112ee287b1fedd981c73a48f85 (diff) | |
download | postgresql-eaf0292c3ba7acac2735f99a8988bd49a26112f5.tar.gz postgresql-eaf0292c3ba7acac2735f99a8988bd49a26112f5.zip |
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
Diffstat (limited to 'src')
-rw-r--r-- | src/backend/commands/tablecmds.c | 14 |
1 files changed, 7 insertions, 7 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index e34d4ccc148..95af5ec2dc7 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -15772,8 +15772,7 @@ CloneRowTriggersToPartition(Relation parent, Relation partition) ScanKeyData key; SysScanDesc scan; HeapTuple tuple; - MemoryContext oldcxt, - perTupCxt; + MemoryContext perTupCxt; ScanKeyInit(&key, Anum_pg_trigger_tgrelid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(parent))); @@ -15783,18 +15782,16 @@ CloneRowTriggersToPartition(Relation parent, Relation partition) perTupCxt = AllocSetContextCreate(CurrentMemoryContext, "clone trig", ALLOCSET_SMALL_SIZES); - oldcxt = MemoryContextSwitchTo(perTupCxt); while (HeapTupleIsValid(tuple = systable_getnext(scan))) { - Form_pg_trigger trigForm; + Form_pg_trigger trigForm = (Form_pg_trigger) GETSTRUCT(tuple); CreateTrigStmt *trigStmt; Node *qual = NULL; Datum value; bool isnull; List *cols = NIL; - - trigForm = (Form_pg_trigger) GETSTRUCT(tuple); + MemoryContext oldcxt; /* * Ignore statement-level triggers; those are not cloned. @@ -15813,6 +15810,9 @@ CloneRowTriggersToPartition(Relation parent, Relation partition) elog(ERROR, "unexpected trigger \"%s\" found", NameStr(trigForm->tgname)); + /* Use short-lived context for CREATE TRIGGER */ + oldcxt = MemoryContextSwitchTo(perTupCxt); + /* * If there is a WHEN clause, generate a 'cooked' version of it that's * appropriate for the partition. @@ -15876,10 +15876,10 @@ CloneRowTriggersToPartition(Relation parent, Relation partition) trigForm->tgfoid, trigForm->oid, qual, false, true); + MemoryContextSwitchTo(oldcxt); MemoryContextReset(perTupCxt); } - MemoryContextSwitchTo(oldcxt); MemoryContextDelete(perTupCxt); systable_endscan(scan); |