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

Commite7428a9

Browse files
Add hardening to catch invalid TIDs in indexes.
Add hardening to the heapam index tuple deletion path to catch TIDs inindex pages that point to a heap item that index tuples should neverpoint to. The corruption we're trying to catch here is particularlytricky to detect, since it typically involves "extra" (corrupt) indextuples, as opposed to the absence of required index tuples in the index.For example, a heap TID from an index page that turns out to point to anLP_UNUSED item in the heap page has a good chance of being caught by oneof the new checks. There is a decent chance that the recently fixedparallel VACUUM bug (see commit9bacec1) would have been caught hadthat particular check been in place for Postgres 14. No backpatch ofthis extra hardening for now, though.Author: Peter Geoghegan <pg@bowt.ie>Reviewed-By: Andres Freund <andres@anarazel.de>Discussion:https://postgr.es/m/CAH2-Wzk-4_raTzawWGaiqNvkpwDXxv3y1AQhQyUeHfkU=tFCeA@mail.gmail.com
1 parentbabbbb5 commite7428a9

File tree

5 files changed

+76
-2
lines changed

5 files changed

+76
-2
lines changed

‎src/backend/access/heap/heapam.c

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7252,6 +7252,63 @@ index_delete_prefetch_buffer(Relation rel,
72527252
}
72537253
#endif
72547254

7255+
/*
7256+
* Helper function for heap_index_delete_tuples. Checks for index corruption
7257+
* involving an invalid TID in index AM caller's index page.
7258+
*
7259+
* This is an ideal place for these checks. The index AM must hold a buffer
7260+
* lock on the index page containing the TIDs we examine here, so we don't
7261+
* have to worry about concurrent VACUUMs at all. We can be sure that the
7262+
* index is corrupt when htid points directly to an LP_UNUSED item or
7263+
* heap-only tuple, which is not the case during standard index scans.
7264+
*/
7265+
staticinlinevoid
7266+
index_delete_check_htid(TM_IndexDeleteOp*delstate,
7267+
Pagepage,OffsetNumbermaxoff,
7268+
ItemPointerhtid,TM_IndexStatus*istatus)
7269+
{
7270+
OffsetNumberindexpagehoffnum=ItemPointerGetOffsetNumber(htid);
7271+
ItemIdiid;
7272+
7273+
Assert(OffsetNumberIsValid(istatus->idxoffnum));
7274+
7275+
if (unlikely(indexpagehoffnum>maxoff))
7276+
ereport(ERROR,
7277+
(errcode(ERRCODE_INDEX_CORRUPTED),
7278+
errmsg_internal("heap tid from index tuple (%u,%u) points past end of heap page line pointer array at offset %u of block %u in index \"%s\"",
7279+
ItemPointerGetBlockNumber(htid),
7280+
indexpagehoffnum,
7281+
istatus->idxoffnum,delstate->iblknum,
7282+
RelationGetRelationName(delstate->irel))));
7283+
7284+
iid=PageGetItemId(page,indexpagehoffnum);
7285+
if (unlikely(!ItemIdIsUsed(iid)))
7286+
ereport(ERROR,
7287+
(errcode(ERRCODE_INDEX_CORRUPTED),
7288+
errmsg_internal("heap tid from index tuple (%u,%u) points to unused heap page item at offset %u of block %u in index \"%s\"",
7289+
ItemPointerGetBlockNumber(htid),
7290+
indexpagehoffnum,
7291+
istatus->idxoffnum,delstate->iblknum,
7292+
RelationGetRelationName(delstate->irel))));
7293+
7294+
if (ItemIdHasStorage(iid))
7295+
{
7296+
HeapTupleHeaderhtup;
7297+
7298+
Assert(ItemIdIsNormal(iid));
7299+
htup= (HeapTupleHeader)PageGetItem(page,iid);
7300+
7301+
if (unlikely(HeapTupleHeaderIsHeapOnly(htup)))
7302+
ereport(ERROR,
7303+
(errcode(ERRCODE_INDEX_CORRUPTED),
7304+
errmsg_internal("heap tid from index tuple (%u,%u) points to heap-only tuple at offset %u of block %u in index \"%s\"",
7305+
ItemPointerGetBlockNumber(htid),
7306+
indexpagehoffnum,
7307+
istatus->idxoffnum,delstate->iblknum,
7308+
RelationGetRelationName(delstate->irel))));
7309+
}
7310+
}
7311+
72557312
/*
72567313
* heapam implementation of tableam's index_delete_tuples interface.
72577314
*
@@ -7446,6 +7503,14 @@ heap_index_delete_tuples(Relation rel, TM_IndexDeleteOp *delstate)
74467503
maxoff=PageGetMaxOffsetNumber(page);
74477504
}
74487505

7506+
/*
7507+
* In passing, detect index corruption involving an index page with a
7508+
* TID that points to a location in the heap that couldn't possibly be
7509+
* correct. We only do this with actual TIDs from caller's index page
7510+
* (not items reached by traversing through a HOT chain).
7511+
*/
7512+
index_delete_check_htid(delstate,page,maxoff,htid,istatus);
7513+
74497514
if (istatus->knowndeletable)
74507515
Assert(!delstate->bottomup&& !istatus->promising);
74517516
else

‎src/backend/access/index/genam.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,8 @@ index_compute_xid_horizon_for_tuples(Relation irel,
303303

304304
Assert(nitems>0);
305305

306+
delstate.irel=irel;
307+
delstate.iblknum=BufferGetBlockNumber(ibuf);
306308
delstate.bottomup= false;
307309
delstate.bottomupfreespace=0;
308310
delstate.ndeltids=0;
@@ -312,16 +314,17 @@ index_compute_xid_horizon_for_tuples(Relation irel,
312314
/* identify what the index tuples about to be deleted point to */
313315
for (inti=0;i<nitems;i++)
314316
{
317+
OffsetNumberoffnum=itemnos[i];
315318
ItemIdiitemid;
316319

317-
iitemid=PageGetItemId(ipage,itemnos[i]);
320+
iitemid=PageGetItemId(ipage,offnum);
318321
itup= (IndexTuple)PageGetItem(ipage,iitemid);
319322

320323
Assert(ItemIdIsDead(iitemid));
321324

322325
ItemPointerCopy(&itup->t_tid,&delstate.deltids[i].tid);
323326
delstate.deltids[i].id=delstate.ndeltids;
324-
delstate.status[i].idxoffnum=InvalidOffsetNumber;/* unused */
327+
delstate.status[i].idxoffnum=offnum;
325328
delstate.status[i].knowndeletable= true;/* LP_DEAD-marked */
326329
delstate.status[i].promising= false;/* unused */
327330
delstate.status[i].freespace=0;/* unused */

‎src/backend/access/nbtree/nbtdedup.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,8 @@ _bt_bottomupdel_pass(Relation rel, Buffer buf, Relation heapRel,
348348
* concerning ourselves with avoiding work during the tableam call. Our
349349
* role in costing the bottom-up deletion process is strictly advisory.
350350
*/
351+
delstate.irel=rel;
352+
delstate.iblknum=BufferGetBlockNumber(buf);
351353
delstate.bottomup= true;
352354
delstate.bottomupfreespace=Max(BLCKSZ /16,newitemsz);
353355
delstate.ndeltids=0;

‎src/backend/access/nbtree/nbtinsert.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2810,6 +2810,8 @@ _bt_simpledel_pass(Relation rel, Buffer buffer, Relation heapRel,
28102810
&ndeadblocks);
28112811

28122812
/* Initialize tableam state that describes index deletion operation */
2813+
delstate.irel=rel;
2814+
delstate.iblknum=BufferGetBlockNumber(buffer);
28132815
delstate.bottomup= false;
28142816
delstate.bottomupfreespace=0;
28152817
delstate.ndeltids=0;

‎src/include/access/tableam.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,8 @@ typedef struct TM_IndexStatus
220220
*/
221221
typedefstructTM_IndexDeleteOp
222222
{
223+
Relationirel;/* Target index relation */
224+
BlockNumberiblknum;/* Index block number (for error reports) */
223225
boolbottomup;/* Bottom-up (not simple) deletion? */
224226
intbottomupfreespace;/* Bottom-up space target */
225227

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp