Skip to content

Commit 260dbf1

Browse files
committed
Fix oversight in handling of modifiedCols since f245236
Commit f245236 fixed a memory leak by moving the modifiedCols bitmap into the per-row memory context. In the case of AFTER UPDATE triggers, the bitmap is however referenced from an event kept until the end of the query, resulting in a use-after-free bug. Fixed by copying the bitmap into the AfterTriggerEvents memory context, which is the one where we keep the trigger events. There's only one place that needs to do the copy, but the memory context may not exist yet. Doing that in a separate function seems more readable. Report by Alexander Pyhalov, fix by me. Backpatch to 13, where the bitmap was added to the event by commit 71d60e2. Reported-by: Alexander Pyhalov Backpatch-through: 13 Discussion: https://postgr.es/m/acddb17c89b0d6cb940eaeda18c08bbe@postgrespro.ru
1 parent c1affa3 commit 260dbf1

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

src/backend/commands/trigger.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3689,6 +3689,37 @@ afterTriggerCheckState(AfterTriggerShared evtshared)
36893689
return ((evtshared->ats_event & AFTER_TRIGGER_INITDEFERRED) != 0);
36903690
}
36913691

3692+
/* ----------
3693+
* afterTriggerCopyBitmap()
3694+
*
3695+
* Copy bitmap into AfterTriggerEvents memory context, which is where the after
3696+
* trigger events are kept.
3697+
* ----------
3698+
*/
3699+
static Bitmapset *
3700+
afterTriggerCopyBitmap(Bitmapset *src)
3701+
{
3702+
Bitmapset *dst;
3703+
MemoryContext oldcxt;
3704+
3705+
if (src == NULL)
3706+
return NULL;
3707+
3708+
/* Create event context if we didn't already */
3709+
if (afterTriggers.event_cxt == NULL)
3710+
afterTriggers.event_cxt =
3711+
AllocSetContextCreate(TopTransactionContext,
3712+
"AfterTriggerEvents",
3713+
ALLOCSET_DEFAULT_SIZES);
3714+
3715+
oldcxt = MemoryContextSwitchTo(afterTriggers.event_cxt);
3716+
3717+
dst = bms_copy(src);
3718+
3719+
MemoryContextSwitchTo(oldcxt);
3720+
3721+
return dst;
3722+
}
36923723

36933724
/* ----------
36943725
* afterTriggerAddEvent()
@@ -5806,7 +5837,7 @@ AfterTriggerSaveEvent(EState *estate, ResultRelInfo *relinfo,
58065837
new_shared.ats_table = transition_capture->tcs_private;
58075838
else
58085839
new_shared.ats_table = NULL;
5809-
new_shared.ats_modifiedcols = modifiedCols;
5840+
new_shared.ats_modifiedcols = afterTriggerCopyBitmap(modifiedCols);
58105841

58115842
afterTriggerAddEvent(&afterTriggers.query_stack[afterTriggers.query_depth].events,
58125843
&new_event, &new_shared);

0 commit comments

Comments
 (0)