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

Commit1487ca0

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 parent69bef7f commit1487ca0

File tree

3 files changed

+49
-33
lines changed

3 files changed

+49
-33
lines changed

‎src/backend/commands/trigger.c

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1620,18 +1620,19 @@ ExecASUpdateTriggers(EState *estate, ResultRelInfo *relinfo)
16201620
false,NULL,NULL);
16211621
}
16221622

1623-
HeapTuple
1623+
TupleTableSlot*
16241624
ExecBRUpdateTriggers(EState*estate,ResultRelInfo*relinfo,
1625-
ItemPointertupleid,HeapTuplenewtuple,
1625+
ItemPointertupleid,TupleTableSlot*slot,
16261626
CommandIdcid)
16271627
{
16281628
TriggerDesc*trigdesc=relinfo->ri_TrigDesc;
16291629
intntrigs=trigdesc->n_before_row[TRIGGER_EVENT_UPDATE];
16301630
int*tgindx=trigdesc->tg_before_row[TRIGGER_EVENT_UPDATE];
1631+
HeapTupleslottuple=ExecMaterializeSlot(slot);
1632+
HeapTuplenewtuple=slottuple;
16311633
TriggerDataLocTriggerData;
16321634
HeapTupletrigtuple;
16331635
HeapTupleoldtuple;
1634-
HeapTupleintuple=newtuple;
16351636
TupleTableSlot*newSlot;
16361637
inti;
16371638

@@ -1640,11 +1641,22 @@ ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
16401641
returnNULL;
16411642

16421643
/*
1643-
* In READ COMMITTED isolation level it's possible that newtuple was
1644-
* changed due to concurrent update.
1644+
* In READ COMMITTED isolation level it's possible that target tuple was
1645+
* changed due to concurrent update. In that case we have a raw subplan
1646+
* output tuple in newSlot, and need to run it through the junk filter to
1647+
* produce an insertable tuple.
1648+
*
1649+
* Caution: more than likely, the passed-in slot is the same as the
1650+
* junkfilter's output slot, so we are clobbering the original value of
1651+
* slottuple by doing the filtering. This is OK since neither we nor our
1652+
* caller have any more interest in the prior contents of that slot.
16451653
*/
16461654
if (newSlot!=NULL)
1647-
intuple=newtuple=ExecRemoveJunk(estate->es_junkFilter,newSlot);
1655+
{
1656+
slot=ExecFilterJunk(estate->es_junkFilter,newSlot);
1657+
slottuple=ExecMaterializeSlot(slot);
1658+
newtuple=slottuple;
1659+
}
16481660

16491661
LocTriggerData.type=T_TriggerData;
16501662
LocTriggerData.tg_event=TRIGGER_EVENT_UPDATE |
@@ -1667,13 +1679,33 @@ ExecBRUpdateTriggers(EState *estate, ResultRelInfo *relinfo,
16671679
relinfo->ri_TrigFunctions,
16681680
relinfo->ri_TrigInstrument,
16691681
GetPerTupleMemoryContext(estate));
1670-
if (oldtuple!=newtuple&&oldtuple!=intuple)
1682+
if (oldtuple!=newtuple&&oldtuple!=slottuple)
16711683
heap_freetuple(oldtuple);
16721684
if (newtuple==NULL)
1673-
break;
1685+
{
1686+
heap_freetuple(trigtuple);
1687+
returnNULL;/* "do nothing" */
1688+
}
16741689
}
16751690
heap_freetuple(trigtuple);
1676-
returnnewtuple;
1691+
1692+
if (newtuple!=slottuple)
1693+
{
1694+
/*
1695+
* Return the modified tuple using the es_trig_tuple_slot. We assume
1696+
* the tuple was allocated in per-tuple memory context, and therefore
1697+
* will go away by itself. The tuple table slot should not try to
1698+
* clear it.
1699+
*/
1700+
TupleTableSlot*newslot=estate->es_trig_tuple_slot;
1701+
TupleDesctupdesc=RelationGetDescr(relinfo->ri_RelationDesc);
1702+
1703+
if (newslot->tts_tupleDescriptor!=tupdesc)
1704+
ExecSetSlotDescriptor(newslot,tupdesc);
1705+
ExecStoreTuple(newtuple,newslot,InvalidBuffer, false);
1706+
slot=newslot;
1707+
}
1708+
returnslot;
16771709
}
16781710

16791711
void

‎src/backend/executor/execMain.c

Lines changed: 6 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1678,31 +1678,15 @@ ExecUpdate(TupleTableSlot *slot,
16781678
if (resultRelInfo->ri_TrigDesc&&
16791679
resultRelInfo->ri_TrigDesc->n_before_row[TRIGGER_EVENT_UPDATE]>0)
16801680
{
1681-
HeapTuplenewtuple;
1682-
1683-
newtuple=ExecBRUpdateTriggers(estate,resultRelInfo,
1684-
tupleid,tuple,
1685-
estate->es_snapshot->curcid);
1681+
slot=ExecBRUpdateTriggers(estate,resultRelInfo,
1682+
tupleid,slot,
1683+
estate->es_snapshot->curcid);
16861684

1687-
if (newtuple==NULL)/* "do nothing" */
1685+
if (slot==NULL)/* "do nothing" */
16881686
return;
16891687

1690-
if (newtuple!=tuple)/* modified by Trigger(s) */
1691-
{
1692-
/*
1693-
* Put the modified tuple into a slot for convenience of routines
1694-
* below. We assume the tuple was allocated in per-tuple memory
1695-
* context, and therefore will go away by itself. The tuple table
1696-
* slot should not try to clear it.
1697-
*/
1698-
TupleTableSlot*newslot=estate->es_trig_tuple_slot;
1699-
1700-
if (newslot->tts_tupleDescriptor!=slot->tts_tupleDescriptor)
1701-
ExecSetSlotDescriptor(newslot,slot->tts_tupleDescriptor);
1702-
ExecStoreTuple(newtuple,newslot,InvalidBuffer, false);
1703-
slot=newslot;
1704-
tuple=newtuple;
1705-
}
1688+
/* trigger might have changed tuple */
1689+
tuple=ExecMaterializeSlot(slot);
17061690
}
17071691

17081692
/*

‎src/include/commands/trigger.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,10 @@ extern void ExecBSUpdateTriggers(EState *estate,
147147
ResultRelInfo*relinfo);
148148
externvoidExecASUpdateTriggers(EState*estate,
149149
ResultRelInfo*relinfo);
150-
externHeapTupleExecBRUpdateTriggers(EState*estate,
150+
externTupleTableSlot*ExecBRUpdateTriggers(EState*estate,
151151
ResultRelInfo*relinfo,
152152
ItemPointertupleid,
153-
HeapTuplenewtuple,
153+
TupleTableSlot*slot,
154154
CommandIdcid);
155155
externvoidExecARUpdateTriggers(EState*estate,
156156
ResultRelInfo*relinfo,

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp