From: Andres Freund Date: Fri, 19 Apr 2019 00:53:54 +0000 (-0700) Subject: Fix potential use-after-free for BEFORE UPDATE row triggers on non-core AMs. X-Git-Tag: REL_12_BETA1~204 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=75e03eabeaac8fd229b14f74de55d0e1470903c4;p=thirdparty%2Fpostgresql.git Fix potential use-after-free for BEFORE UPDATE row triggers on non-core AMs. When such a trigger returns the old row version, it naturally get stored in the slot for the trigger result. When a table AMs doesn't store HeapTuples internally, ExecBRUpdateTriggers() frees the old row version passed to triggers - but before this fix it might still be referenced by the slot holding the new tuple. Noticed when running the out-of-core zheap AM against the in-core version of tableam. Author: Andres Freund --- diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index 3ae2640abd4..c81ccc8fcff 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -3109,6 +3109,15 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate, { ExecForceStoreHeapTuple(newtuple, newslot); + /* + * If the tuple returned by the trigger / being stored, is the old + * row version, and the heap tuple passed to the trigger was + * allocated locally, materialize the slot. Otherwise we might + * free it while still referenced by the slot. + */ + if (should_free_trig && newtuple == trigtuple) + ExecMaterializeSlot(newslot); + if (should_free_new) heap_freetuple(oldtuple);