Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 48a565d

Browse files
committed
Fix reference-after-free when waiting for another xact due to constraint.
If an insertion or update had to wait for another transaction to finish, because there was another insertion with conflicting key in progress, we would pass a just-free'd item pointer to XactLockTableWait(). All calls to XactLockTableWait() and MultiXactIdWait() had similar issues. Some passed a pointer to a buffer in the buffer cache, after already releasing the lock. The call in EvalPlanQualFetch had already released the pin too. All but the call in execUtils.c would merely lead to reporting a bogus ctid, however (or an assertion failure, if enabled). All the callers that passed HeapTuple->t_data->t_ctid were slightly bogus anyway: if the tuple was updated (again) in the same transaction, its ctid field would point to the next tuple in the chain, not the tuple itself. Backpatch to 9.4, where the 'ctid' argument to XactLockTableWait was added (in commit f88d4cf)
1 parent 742734d commit 48a565d

File tree

4 files changed

+14
-12
lines changed

4 files changed

+14
-12
lines changed

src/backend/access/heap/heapam.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2742,7 +2742,7 @@ heap_delete(Relation relation, ItemPointer tid,
27422742
{
27432743
/* wait for multixact */
27442744
MultiXactIdWait((MultiXactId) xwait, MultiXactStatusUpdate, infomask,
2745-
relation, &tp.t_data->t_ctid, XLTW_Delete,
2745+
relation, &(tp.t_self), XLTW_Delete,
27462746
NULL);
27472747
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
27482748

@@ -2769,7 +2769,7 @@ heap_delete(Relation relation, ItemPointer tid,
27692769
else
27702770
{
27712771
/* wait for regular transaction to end */
2772-
XactLockTableWait(xwait, relation, &tp.t_data->t_ctid, XLTW_Delete);
2772+
XactLockTableWait(xwait, relation, &(tp.t_self), XLTW_Delete);
27732773
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
27742774

27752775
/*
@@ -3298,7 +3298,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
32983298

32993299
/* wait for multixact */
33003300
MultiXactIdWait((MultiXactId) xwait, mxact_status, infomask,
3301-
relation, &oldtup.t_data->t_ctid, XLTW_Update,
3301+
relation, &oldtup.t_self, XLTW_Update,
33023302
&remain);
33033303
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
33043304

@@ -3378,7 +3378,7 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
33783378
*/
33793379
heap_acquire_tuplock(relation, &(oldtup.t_self), *lockmode,
33803380
false, &have_tuple_lock);
3381-
XactLockTableWait(xwait, relation, &oldtup.t_data->t_ctid,
3381+
XactLockTableWait(xwait, relation, &oldtup.t_self,
33823382
XLTW_Update);
33833383
LockBuffer(buffer, BUFFER_LOCK_EXCLUSIVE);
33843384

@@ -4396,7 +4396,7 @@ heap_lock_tuple(Relation relation, HeapTuple tuple,
43964396
}
43974397
else
43984398
MultiXactIdWait((MultiXactId) xwait, status, infomask,
4399-
relation, &tuple->t_data->t_ctid,
4399+
relation, &tuple->t_self,
44004400
XLTW_Lock, NULL);
44014401

44024402
/* if there are updates, follow the update chain */
@@ -4452,7 +4452,7 @@ heap_lock_tuple(Relation relation, HeapTuple tuple,
44524452
RelationGetRelationName(relation))));
44534453
}
44544454
else
4455-
XactLockTableWait(xwait, relation, &tuple->t_data->t_ctid,
4455+
XactLockTableWait(xwait, relation, &tuple->t_self,
44564456
XLTW_Lock);
44574457

44584458
/* if there are updates, follow the update chain */
@@ -5168,7 +5168,7 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
51685168
{
51695169
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
51705170
XactLockTableWait(members[i].xid, rel,
5171-
&mytup.t_data->t_ctid,
5171+
&mytup.t_self,
51725172
XLTW_LockUpdated);
51735173
pfree(members);
51745174
goto l4;
@@ -5229,7 +5229,7 @@ heap_lock_updated_tuple_rec(Relation rel, ItemPointer tid, TransactionId xid,
52295229
if (needwait)
52305230
{
52315231
LockBuffer(buf, BUFFER_LOCK_UNLOCK);
5232-
XactLockTableWait(rawxmax, rel, &mytup.t_data->t_ctid,
5232+
XactLockTableWait(rawxmax, rel, &mytup.t_self,
52335233
XLTW_LockUpdated);
52345234
goto l4;
52355235
}

src/backend/catalog/index.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2288,7 +2288,7 @@ IndexBuildHeapScan(Relation heapRelation,
22882288
*/
22892289
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
22902290
XactLockTableWait(xwait, heapRelation,
2291-
&heapTuple->t_data->t_ctid,
2291+
&heapTuple->t_self,
22922292
XLTW_InsertIndexUnique);
22932293
CHECK_FOR_INTERRUPTS();
22942294
goto recheck;
@@ -2337,7 +2337,7 @@ IndexBuildHeapScan(Relation heapRelation,
23372337
*/
23382338
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);
23392339
XactLockTableWait(xwait, heapRelation,
2340-
&heapTuple->t_data->t_ctid,
2340+
&heapTuple->t_self,
23412341
XLTW_InsertIndexUnique);
23422342
CHECK_FOR_INTERRUPTS();
23432343
goto recheck;

src/backend/executor/execMain.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2104,7 +2104,7 @@ EvalPlanQualFetch(EState *estate, Relation relation, int lockmode, bool noWait,
21042104
}
21052105
else
21062106
XactLockTableWait(SnapshotDirty.xmax,
2107-
relation, &tuple.t_data->t_ctid,
2107+
relation, &tuple.t_self,
21082108
XLTW_FetchUpdated);
21092109
continue; /* loop back to repeat heap_fetch */
21102110
}

src/backend/executor/execUtils.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1245,6 +1245,7 @@ check_exclusion_constraint(Relation heap, Relation index, IndexInfo *indexInfo,
12451245
ForwardScanDirection)) != NULL)
12461246
{
12471247
TransactionId xwait;
1248+
ItemPointerData ctid_wait;
12481249
Datum existing_values[INDEX_MAX_KEYS];
12491250
bool existing_isnull[INDEX_MAX_KEYS];
12501251
char *error_new;
@@ -1306,8 +1307,9 @@ check_exclusion_constraint(Relation heap, Relation index, IndexInfo *indexInfo,
13061307

13071308
if (TransactionIdIsValid(xwait))
13081309
{
1310+
ctid_wait = tup->t_data->t_ctid;
13091311
index_endscan(index_scan);
1310-
XactLockTableWait(xwait, heap, &tup->t_data->t_ctid,
1312+
XactLockTableWait(xwait, heap, &ctid_wait,
13111313
XLTW_RecheckExclusionConstr);
13121314
goto retry;
13131315
}

0 commit comments

Comments
 (0)