Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1a4e546

Browse files
committed
Prevent access to an unpinned buffer in BEFORE ROW UPDATE triggers.
When ExecBRUpdateTriggers switches to a new target tuple as a resultof the EvalPlanQual logic, it must form a new proposed update tuple.Since commit86dc900, that tuple (the result ofExecGetUpdateNewTuple) has been a virtual tuple that might containpointers to by-ref fields of the new target tuple (in "oldslot").However, immediately after that we materialize oldslot, causing it todrop its buffer pin, whereupon the by-ref pointers are unsafe to use.This is a live bug only when the new target tuple is in a differentpage than the original target tuple, since we do still hold a pin onthe original one. (Before86dc900, there was no bug because theEPQ plantree would hold a pin on the new target tuple; but now that'snot assured.) To fix, forcibly materialize the new tuple before wematerialize oldslot. This costs nothing since we would have done thatshortly anyway.The real-world impact of this is probably minimal. A visible failurecould occur if the new target tuple's buffer were recycled for someother page in the short interval before we materialize newslot withinthe trigger-calling loop; but that's quite unlikely given that we'djust touched that page. There's a larger hazard that some otherprocess could prune and repack that page within the window. We havelock on the new target tuple, but that wouldn't prevent it being movedon the page.Alexander Lakhin and Tom Lane, per bug #17798 from Alexander Lakhin.Back-patch to v14 where86dc900 came in.Discussion:https://postgr.es/m/17798-0907404928dcf0dd@postgresql.org
1 parentd41358f commit1a4e546

File tree

1 file changed

+23
-5
lines changed

1 file changed

+23
-5
lines changed

‎src/backend/commands/trigger.c

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3056,10 +3056,6 @@ ExecBRUpdateTriggersNew(EState *estate, EPQState *epqstate,
30563056
* received in newslot. Neither we nor our callers have any further
30573057
* interest in the passed-in tuple, so it's okay to overwrite newslot
30583058
* with the newer data.
3059-
*
3060-
* (Typically, newslot was also generated by ExecGetUpdateNewTuple, so
3061-
* that epqslot_clean will be that same slot and the copy step below
3062-
* is not needed.)
30633059
*/
30643060
if (epqslot_candidate!=NULL)
30653061
{
@@ -3068,14 +3064,36 @@ ExecBRUpdateTriggersNew(EState *estate, EPQState *epqstate,
30683064
epqslot_clean=ExecGetUpdateNewTuple(relinfo,epqslot_candidate,
30693065
oldslot);
30703066

3071-
if (newslot!=epqslot_clean)
3067+
/*
3068+
* Typically, the caller's newslot was also generated by
3069+
* ExecGetUpdateNewTuple, so that epqslot_clean will be the same
3070+
* slot and copying is not needed. But do the right thing if it
3071+
* isn't.
3072+
*/
3073+
if (unlikely(newslot!=epqslot_clean))
30723074
ExecCopySlot(newslot,epqslot_clean);
3075+
3076+
/*
3077+
* At this point newslot contains a virtual tuple that may
3078+
* reference some fields of oldslot's tuple in some disk buffer.
3079+
* If that tuple is in a different page than the original target
3080+
* tuple, then our only pin on that buffer is oldslot's, and we're
3081+
* about to release it. Hence we'd better materialize newslot to
3082+
* ensure it doesn't contain references into an unpinned buffer.
3083+
* (We'd materialize it below anyway, but too late for safety.)
3084+
*/
3085+
ExecMaterializeSlot(newslot);
30733086
}
30743087

3088+
/*
3089+
* Here we convert oldslot to a materialized slot holding trigtuple.
3090+
* Neither slot passed to the triggers will hold any buffer pin.
3091+
*/
30753092
trigtuple=ExecFetchSlotHeapTuple(oldslot, true,&should_free_trig);
30763093
}
30773094
else
30783095
{
3096+
/* Put the FDW-supplied tuple into oldslot to unify the cases */
30793097
ExecForceStoreHeapTuple(fdw_trigtuple,oldslot, false);
30803098
trigtuple=fdw_trigtuple;
30813099
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp