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

Commit15907c3

Browse files
committed
Fix dangling-pointer problem in before-row update trigger processing.
ExecUpdate checked for whether ExecBRUpdateTriggers had returned a newtuple value by seeing if the returned tuple was pointer-equal to the oldone. But the "old one" was in estate->es_junkFilter's result slot, whichwould be scribbled on if we had done an EvalPlanQual update in response toa concurrent update of the target tuple; therefore we were comparing adangling pointer to a live one. Given the right set of circumstances wecould get a false match, resulting in not forcing the tuple to be stored inthe slot we thought it was stored in. In the case reported by Maxim Bogukin bug #5798, this led to "cannot extract system attribute from virtualtuple" failures when trying to do "RETURNING ctid". I believe there is avery-low-probability chance of more serious errors, such as generatingincorrect index entries based on the original rather than thetrigger-modified version of the row.In HEAD, change all of ExecBRInsertTriggers, ExecIRInsertTriggers,ExecBRUpdateTriggers, and ExecIRUpdateTriggers so that they continue tohave similar APIs. In the back branches I just changedExecBRUpdateTriggers, since there is no bug in the ExecBRInsertTriggerscase.
1 parentb22e2d6 commit15907c3

File tree

3 files changed

+47
-33
lines changed

3 files changed

+47
-33
lines changed

‎src/backend/commands/trigger.c

Lines changed: 40 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2172,18 +2172,19 @@ ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
21722172
GetModifiedColumns(relinfo,estate));
21732173
}
21742174

2175-
HeapTuple
2175+
TupleTableSlot*
21762176
ExecBRUpdateTriggers(EState*estate,EPQState*epqstate,
21772177
ResultRelInfo*relinfo,
2178-
ItemPointertupleid,HeapTuplenewtuple)
2178+
ItemPointertupleid,TupleTableSlot*slot)
21792179
{
21802180
TriggerDesc*trigdesc=relinfo->ri_TrigDesc;
21812181
intntrigs=trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
21822182
int*tgindx=trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
2183+
HeapTupleslottuple=ExecMaterializeSlot(slot);
2184+
HeapTuplenewtuple=slottuple;
21832185
TriggerDataLocTriggerData;
21842186
HeapTupletrigtuple;
21852187
HeapTupleoldtuple;
2186-
HeapTupleintuple=newtuple;
21872188
TupleTableSlot*newSlot;
21882189
inti;
21892190
Bitmapset*modifiedCols;
@@ -2194,12 +2195,22 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
21942195
returnNULL;
21952196

21962197
/*
2197-
* In READ COMMITTED isolation level it's possible thatnewtuple was
2198+
* In READ COMMITTED isolation level it's possible thattarget tuple was
21982199
* changed due to concurrent update. In that case we have a raw subplan
2199-
* output tuple and need to run it through the junk filter.
2200+
* output tuple in newSlot, and need to run it through the junk filter to
2201+
* produce an insertable tuple.
2202+
*
2203+
* Caution: more than likely, the passed-in slot is the same as the
2204+
* junkfilter's output slot, so we are clobbering the original value of
2205+
* slottuple by doing the filtering. This is OK since neither we nor our
2206+
* caller have any more interest in the prior contents of that slot.
22002207
*/
22012208
if (newSlot!=NULL)
2202-
intuple=newtuple=ExecRemoveJunk(relinfo->ri_junkFilter,newSlot);
2209+
{
2210+
slot=ExecFilterJunk(relinfo->ri_junkFilter,newSlot);
2211+
slottuple=ExecMaterializeSlot(slot);
2212+
newtuple=slottuple;
2213+
}
22032214

22042215
modifiedCols=GetModifiedColumns(relinfo,estate);
22052216

@@ -2226,13 +2237,33 @@ ExecBRUpdateTriggers(EState *estate, EPQState *epqstate,
22262237
relinfo->ri_TrigFunctions,
22272238
relinfo->ri_TrigInstrument,
22282239
GetPerTupleMemoryContext(estate));
2229-
if (oldtuple!=newtuple&&oldtuple!=intuple)
2240+
if (oldtuple!=newtuple&&oldtuple!=slottuple)
22302241
heap_freetuple(oldtuple);
22312242
if (newtuple==NULL)
2232-
break;
2243+
{
2244+
heap_freetuple(trigtuple);
2245+
returnNULL;/* "do nothing" */
2246+
}
22332247
}
22342248
heap_freetuple(trigtuple);
2235-
returnnewtuple;
2249+
2250+
if (newtuple!=slottuple)
2251+
{
2252+
/*
2253+
* Return the modified tuple using the es_trig_tuple_slot. We assume
2254+
* the tuple was allocated in per-tuple memory context, and therefore
2255+
* will go away by itself. The tuple table slot should not try to
2256+
* clear it.
2257+
*/
2258+
TupleTableSlot*newslot=estate->es_trig_tuple_slot;
2259+
TupleDesctupdesc=RelationGetDescr(relinfo->ri_RelationDesc);
2260+
2261+
if (newslot->tts_tupleDescriptor!=tupdesc)
2262+
ExecSetSlotDescriptor(newslot,tupdesc);
2263+
ExecStoreTuple(newtuple,newslot,InvalidBuffer, false);
2264+
slot=newslot;
2265+
}
2266+
returnslot;
22362267
}
22372268

22382269
void

‎src/backend/executor/nodeModifyTable.c

Lines changed: 5 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -453,31 +453,14 @@ ExecUpdate(ItemPointer tupleid,
453453
if (resultRelInfo->ri_TrigDesc&&
454454
resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_UPDATE]>0)
455455
{
456-
HeapTuplenewtuple;
457-
458-
newtuple=ExecBRUpdateTriggers(estate,epqstate,resultRelInfo,
459-
tupleid,tuple);
456+
slot=ExecBRUpdateTriggers(estate,epqstate,resultRelInfo,
457+
tupleid,slot);
460458

461-
if (newtuple==NULL)/* "do nothing" */
459+
if (slot==NULL)/* "do nothing" */
462460
returnNULL;
463461

464-
if (newtuple!=tuple)/* modified by Trigger(s) */
465-
{
466-
/*
467-
* Put the modified tuple into a slot for convenience of routines
468-
* below. We assume the tuple was allocated in per-tuple memory
469-
* context, and therefore will go away by itself. The tuple table
470-
* slot should not try to clear it.
471-
*/
472-
TupleTableSlot*newslot=estate->es_trig_tuple_slot;
473-
TupleDesctupdesc=RelationGetDescr(resultRelationDesc);
474-
475-
if (newslot->tts_tupleDescriptor!=tupdesc)
476-
ExecSetSlotDescriptor(newslot,tupdesc);
477-
ExecStoreTuple(newtuple,newslot,InvalidBuffer, false);
478-
slot=newslot;
479-
tuple=newtuple;
480-
}
462+
/* trigger might have changed tuple */
463+
tuple=ExecMaterializeSlot(slot);
481464
}
482465

483466
/*

‎src/include/commands/trigger.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,11 +149,11 @@ extern void ExecBSUpdateTriggers(EState *estate,
149149
ResultRelInfo*relinfo);
150150
externvoidExecASUpdateTriggers(EState*estate,
151151
ResultRelInfo*relinfo);
152-
externHeapTupleExecBRUpdateTriggers(EState*estate,
152+
externTupleTableSlot*ExecBRUpdateTriggers(EState*estate,
153153
EPQState*epqstate,
154154
ResultRelInfo*relinfo,
155155
ItemPointertupleid,
156-
HeapTuplenewtuple);
156+
TupleTableSlot*slot);
157157
externvoidExecARUpdateTriggers(EState*estate,
158158
ResultRelInfo*relinfo,
159159
ItemPointertupleid,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp