aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/trigger.c
diff options
context:
space:
mode:
authorAndres Freund <andres@anarazel.de>2019-04-18 17:53:54 -0700
committerAndres Freund <andres@anarazel.de>2019-04-18 17:53:54 -0700
commit75e03eabeaac8fd229b14f74de55d0e1470903c4 (patch)
treee18a589b1382a6d5140f42169c151e90c7f3a6c8 /src/backend/commands/trigger.c
parentbb385c4fb0f4eb33d2bc7e484061565ba51cc790 (diff)
downloadpostgresql-75e03eabeaac8fd229b14f74de55d0e1470903c4.tar.gz
postgresql-75e03eabeaac8fd229b14f74de55d0e1470903c4.zip
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
Diffstat (limited to 'src/backend/commands/trigger.c')
-rw-r--r--src/backend/commands/trigger.c9
1 files changed, 9 insertions, 0 deletions
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);