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

Commit766dc45

Browse files
committed
Add defenses to btree and hash index AMs to do simple sanity checks
on every index page they read; in particular to catch the case of anall-zero page, which PageHeaderIsValid allows to pass. It turns outhash already had this idea, but it was just Assert()ing things ratherthan doing a straight error check, and the Asserts were partiallyredundant with PageHeaderIsValid anyway. Per recent failure examplefrom Jim Nasby. (gist still needs the same treatment.)
1 parent18691d8 commit766dc45

File tree

11 files changed

+147
-79
lines changed

11 files changed

+147
-79
lines changed

‎src/backend/access/hash/hash.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.81 2005/10/15 02:49:08 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.82 2005/11/06 19:29:00 tgl Exp $
1212
*
1313
* NOTES
1414
* This file contains only the public interface routines.
@@ -513,8 +513,8 @@ hashbulkdelete(PG_FUNCTION_ARGS)
513513
* each bucket.
514514
*/
515515
metabuf=_hash_getbuf(rel,HASH_METAPAGE,HASH_READ);
516+
_hash_checkpage(rel,metabuf,LH_META_PAGE);
516517
metap= (HashMetaPage)BufferGetPage(metabuf);
517-
_hash_checkpage(rel, (Page)metap,LH_META_PAGE);
518518
orig_maxbucket=metap->hashm_maxbucket;
519519
orig_ntuples=metap->hashm_ntuples;
520520
memcpy(&local_metapage,metap,sizeof(local_metapage));
@@ -555,8 +555,8 @@ hashbulkdelete(PG_FUNCTION_ARGS)
555555
vacuum_delay_point();
556556

557557
buf=_hash_getbuf(rel,blkno,HASH_WRITE);
558+
_hash_checkpage(rel,buf,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
558559
page=BufferGetPage(buf);
559-
_hash_checkpage(rel,page,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
560560
opaque= (HashPageOpaque)PageGetSpecialPointer(page);
561561
Assert(opaque->hasho_bucket==cur_bucket);
562562

@@ -614,8 +614,8 @@ hashbulkdelete(PG_FUNCTION_ARGS)
614614

615615
/* Write-lock metapage and check for split since we started */
616616
metabuf=_hash_getbuf(rel,HASH_METAPAGE,HASH_WRITE);
617+
_hash_checkpage(rel,metabuf,LH_META_PAGE);
617618
metap= (HashMetaPage)BufferGetPage(metabuf);
618-
_hash_checkpage(rel, (Page)metap,LH_META_PAGE);
619619

620620
if (cur_maxbucket!=metap->hashm_maxbucket)
621621
{

‎src/backend/access/hash/hashinsert.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.39 2005/10/18 01:06:23 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/hash/hashinsert.c,v 1.40 2005/11/06 19:29:00 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -73,8 +73,8 @@ _hash_doinsert(Relation rel, HashItem hitem)
7373

7474
/* Read the metapage */
7575
metabuf=_hash_getbuf(rel,HASH_METAPAGE,HASH_READ);
76+
_hash_checkpage(rel,metabuf,LH_META_PAGE);
7677
metap= (HashMetaPage)BufferGetPage(metabuf);
77-
_hash_checkpage(rel, (Page)metap,LH_META_PAGE);
7878

7979
/*
8080
* Check whether the item can fit on a hash page at all. (Eventually, we
@@ -111,8 +111,8 @@ _hash_doinsert(Relation rel, HashItem hitem)
111111

112112
/* Fetch the primary bucket page for the bucket */
113113
buf=_hash_getbuf(rel,blkno,HASH_WRITE);
114+
_hash_checkpage(rel,buf,LH_BUCKET_PAGE);
114115
page=BufferGetPage(buf);
115-
_hash_checkpage(rel,page,LH_BUCKET_PAGE);
116116
pageopaque= (HashPageOpaque)PageGetSpecialPointer(page);
117117
Assert(pageopaque->hasho_bucket==bucket);
118118

@@ -151,7 +151,7 @@ _hash_doinsert(Relation rel, HashItem hitem)
151151
/* should fit now, given test above */
152152
Assert(PageGetFreeSpace(page) >=itemsz);
153153
}
154-
_hash_checkpage(rel,page,LH_OVERFLOW_PAGE);
154+
_hash_checkpage(rel,buf,LH_OVERFLOW_PAGE);
155155
pageopaque= (HashPageOpaque)PageGetSpecialPointer(page);
156156
Assert(pageopaque->hasho_bucket==bucket);
157157
}
@@ -204,8 +204,8 @@ _hash_pgaddtup(Relation rel,
204204
OffsetNumberitup_off;
205205
Pagepage;
206206

207+
_hash_checkpage(rel,buf,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
207208
page=BufferGetPage(buf);
208-
_hash_checkpage(rel,page,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
209209

210210
itup_off=OffsetNumberNext(PageGetMaxOffsetNumber(page));
211211
if (PageAddItem(page, (Item)hitem,itemsize,itup_off,LP_USED)

‎src/backend/access/hash/hashovfl.c

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.47 2005/10/15 02:49:08 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/hash/hashovfl.c,v 1.48 2005/11/06 19:29:00 tgl Exp $
1212
*
1313
* NOTES
1414
* Overflow pages look like ordinary relation pages.
@@ -124,8 +124,8 @@ _hash_addovflpage(Relation rel, Buffer metabuf, Buffer buf)
124124
{
125125
BlockNumbernextblkno;
126126

127+
_hash_checkpage(rel,buf,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
127128
page=BufferGetPage(buf);
128-
_hash_checkpage(rel,page,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
129129
pageopaque= (HashPageOpaque)PageGetSpecialPointer(page);
130130
nextblkno=pageopaque->hasho_nextblkno;
131131

@@ -183,8 +183,8 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
183183
/* Get exclusive lock on the meta page */
184184
_hash_chgbufaccess(rel,metabuf,HASH_NOLOCK,HASH_WRITE);
185185

186+
_hash_checkpage(rel,metabuf,LH_META_PAGE);
186187
metap= (HashMetaPage)BufferGetPage(metabuf);
187-
_hash_checkpage(rel, (Page)metap,LH_META_PAGE);
188188

189189
/* start search at hashm_firstfree */
190190
orig_firstfree=metap->hashm_firstfree;
@@ -222,8 +222,8 @@ _hash_getovflpage(Relation rel, Buffer metabuf)
222222
_hash_chgbufaccess(rel,metabuf,HASH_READ,HASH_NOLOCK);
223223

224224
mapbuf=_hash_getbuf(rel,mapblkno,HASH_WRITE);
225+
_hash_checkpage(rel,mapbuf,LH_BITMAP_PAGE);
225226
mappage=BufferGetPage(mapbuf);
226-
_hash_checkpage(rel,mappage,LH_BITMAP_PAGE);
227227
freep=HashPageGetBitmap(mappage);
228228

229229
for (;bit <=last_inpage;j++,bit+=BITS_PER_MAP)
@@ -379,9 +379,9 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
379379
Bucketbucket;
380380

381381
/* Get information from the doomed page */
382+
_hash_checkpage(rel,ovflbuf,LH_OVERFLOW_PAGE);
382383
ovflblkno=BufferGetBlockNumber(ovflbuf);
383384
ovflpage=BufferGetPage(ovflbuf);
384-
_hash_checkpage(rel,ovflpage,LH_OVERFLOW_PAGE);
385385
ovflopaque= (HashPageOpaque)PageGetSpecialPointer(ovflpage);
386386
nextblkno=ovflopaque->hasho_nextblkno;
387387
prevblkno=ovflopaque->hasho_prevblkno;
@@ -403,7 +403,7 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
403403
Pageprevpage=BufferGetPage(prevbuf);
404404
HashPageOpaqueprevopaque= (HashPageOpaque)PageGetSpecialPointer(prevpage);
405405

406-
_hash_checkpage(rel,prevpage,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
406+
_hash_checkpage(rel,prevbuf,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
407407
Assert(prevopaque->hasho_bucket==bucket);
408408
prevopaque->hasho_nextblkno=nextblkno;
409409
_hash_wrtbuf(rel,prevbuf);
@@ -414,16 +414,16 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
414414
Pagenextpage=BufferGetPage(nextbuf);
415415
HashPageOpaquenextopaque= (HashPageOpaque)PageGetSpecialPointer(nextpage);
416416

417-
_hash_checkpage(rel,nextpage,LH_OVERFLOW_PAGE);
417+
_hash_checkpage(rel,nextbuf,LH_OVERFLOW_PAGE);
418418
Assert(nextopaque->hasho_bucket==bucket);
419419
nextopaque->hasho_prevblkno=prevblkno;
420420
_hash_wrtbuf(rel,nextbuf);
421421
}
422422

423423
/* Read the metapage so we can determine which bitmap page to use */
424424
metabuf=_hash_getbuf(rel,HASH_METAPAGE,HASH_READ);
425+
_hash_checkpage(rel,metabuf,LH_META_PAGE);
425426
metap= (HashMetaPage)BufferGetPage(metabuf);
426-
_hash_checkpage(rel, (Page)metap,LH_META_PAGE);
427427

428428
/* Identify which bit to set */
429429
ovflbitno=blkno_to_bitno(metap,ovflblkno);
@@ -440,8 +440,8 @@ _hash_freeovflpage(Relation rel, Buffer ovflbuf)
440440

441441
/* Clear the bitmap bit to indicate that this overflow page is free */
442442
mapbuf=_hash_getbuf(rel,blkno,HASH_WRITE);
443+
_hash_checkpage(rel,mapbuf,LH_BITMAP_PAGE);
443444
mappage=BufferGetPage(mapbuf);
444-
_hash_checkpage(rel,mappage,LH_BITMAP_PAGE);
445445
freep=HashPageGetBitmap(mappage);
446446
Assert(ISSET(freep,bitmapbit));
447447
CLRBIT(freep,bitmapbit);
@@ -569,8 +569,8 @@ _hash_squeezebucket(Relation rel,
569569
*/
570570
wblkno=bucket_blkno;
571571
wbuf=_hash_getbuf(rel,wblkno,HASH_WRITE);
572+
_hash_checkpage(rel,wbuf,LH_BUCKET_PAGE);
572573
wpage=BufferGetPage(wbuf);
573-
_hash_checkpage(rel,wpage,LH_BUCKET_PAGE);
574574
wopaque= (HashPageOpaque)PageGetSpecialPointer(wpage);
575575

576576
/*
@@ -593,8 +593,8 @@ _hash_squeezebucket(Relation rel,
593593
if (ropaque!=wopaque)
594594
_hash_relbuf(rel,rbuf);
595595
rbuf=_hash_getbuf(rel,rblkno,HASH_WRITE);
596+
_hash_checkpage(rel,rbuf,LH_OVERFLOW_PAGE);
596597
rpage=BufferGetPage(rbuf);
597-
_hash_checkpage(rel,rpage,LH_OVERFLOW_PAGE);
598598
ropaque= (HashPageOpaque)PageGetSpecialPointer(rpage);
599599
Assert(ropaque->hasho_bucket==bucket);
600600
}while (BlockNumberIsValid(ropaque->hasho_nextblkno));
@@ -635,8 +635,8 @@ _hash_squeezebucket(Relation rel,
635635
}
636636

637637
wbuf=_hash_getbuf(rel,wblkno,HASH_WRITE);
638+
_hash_checkpage(rel,wbuf,LH_OVERFLOW_PAGE);
638639
wpage=BufferGetPage(wbuf);
639-
_hash_checkpage(rel,wpage,LH_OVERFLOW_PAGE);
640640
wopaque= (HashPageOpaque)PageGetSpecialPointer(wpage);
641641
Assert(wopaque->hasho_bucket==bucket);
642642
}
@@ -688,8 +688,8 @@ _hash_squeezebucket(Relation rel,
688688
_hash_freeovflpage(rel,rbuf);
689689

690690
rbuf=_hash_getbuf(rel,rblkno,HASH_WRITE);
691+
_hash_checkpage(rel,rbuf,LH_OVERFLOW_PAGE);
691692
rpage=BufferGetPage(rbuf);
692-
_hash_checkpage(rel,rpage,LH_OVERFLOW_PAGE);
693693
ropaque= (HashPageOpaque)PageGetSpecialPointer(rpage);
694694
Assert(ropaque->hasho_bucket==bucket);
695695

‎src/backend/access/hash/hashpage.c

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.52 2005/10/15 02:49:08 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/hash/hashpage.c,v 1.53 2005/11/06 19:29:00 tgl Exp $
1212
*
1313
* NOTES
1414
* Postgres hash pages look like ordinary relation pages. The opaque
@@ -103,9 +103,11 @@ _hash_droplock(Relation rel, BlockNumber whichlock, int access)
103103
*(ie, the buffer is "locked and pinned").
104104
*
105105
*XXX P_NEW is not used because, unlike the tree structures, we
106-
*need the bucket blocks to be at certain block numbers.we must
107-
*depend on the caller to call _hash_pageinit on the block if it
108-
*knows that this is a new block.
106+
*need the bucket blocks to be at certain block numbers.
107+
*
108+
*All call sites should call either _hash_pageinit or _hash_checkpage
109+
*on the returned page, depending on whether the block is expected
110+
*to be new or not.
109111
*/
110112
Buffer
111113
_hash_getbuf(Relationrel,BlockNumberblkno,intaccess)
@@ -380,8 +382,8 @@ _hash_expandtable(Relation rel, Buffer metabuf)
380382
/* Write-lock the meta page */
381383
_hash_chgbufaccess(rel,metabuf,HASH_NOLOCK,HASH_WRITE);
382384

385+
_hash_checkpage(rel,metabuf,LH_META_PAGE);
383386
metap= (HashMetaPage)BufferGetPage(metabuf);
384-
_hash_checkpage(rel, (Page)metap,LH_META_PAGE);
385387

386388
/*
387389
* Check to see if split is still needed; someone else might have already
@@ -555,15 +557,15 @@ _hash_splitbucket(Relation rel,
555557
* either bucket.
556558
*/
557559
oblkno=start_oblkno;
558-
nblkno=start_nblkno;
559560
obuf=_hash_getbuf(rel,oblkno,HASH_WRITE);
560-
nbuf=_hash_getbuf(rel,nblkno,HASH_WRITE);
561+
_hash_checkpage(rel,obuf,LH_BUCKET_PAGE);
561562
opage=BufferGetPage(obuf);
562-
npage=BufferGetPage(nbuf);
563-
564-
_hash_checkpage(rel,opage,LH_BUCKET_PAGE);
565563
oopaque= (HashPageOpaque)PageGetSpecialPointer(opage);
566564

565+
nblkno=start_nblkno;
566+
nbuf=_hash_getbuf(rel,nblkno,HASH_WRITE);
567+
npage=BufferGetPage(nbuf);
568+
567569
/* initialize the new bucket's primary page */
568570
_hash_pageinit(npage,BufferGetPageSize(nbuf));
569571
nopaque= (HashPageOpaque)PageGetSpecialPointer(npage);
@@ -602,8 +604,8 @@ _hash_splitbucket(Relation rel,
602604
_hash_wrtbuf(rel,obuf);
603605

604606
obuf=_hash_getbuf(rel,oblkno,HASH_WRITE);
607+
_hash_checkpage(rel,obuf,LH_OVERFLOW_PAGE);
605608
opage=BufferGetPage(obuf);
606-
_hash_checkpage(rel,opage,LH_OVERFLOW_PAGE);
607609
oopaque= (HashPageOpaque)PageGetSpecialPointer(opage);
608610
ooffnum=FirstOffsetNumber;
609611
omaxoffnum=PageGetMaxOffsetNumber(opage);
@@ -642,8 +644,8 @@ _hash_splitbucket(Relation rel,
642644
_hash_chgbufaccess(rel,nbuf,HASH_WRITE,HASH_NOLOCK);
643645
/* chain to a new overflow page */
644646
nbuf=_hash_addovflpage(rel,metabuf,nbuf);
647+
_hash_checkpage(rel,nbuf,LH_OVERFLOW_PAGE);
645648
npage=BufferGetPage(nbuf);
646-
_hash_checkpage(rel,npage,LH_OVERFLOW_PAGE);
647649
/* we don't need nopaque within the loop */
648650
}
649651

‎src/backend/access/hash/hashsearch.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.41 2005/10/18 01:06:23 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.42 2005/11/06 19:29:00 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -53,8 +53,8 @@ _hash_next(IndexScanDesc scan, ScanDirection dir)
5353
/* if we're here, _hash_step found a valid tuple */
5454
current=&(scan->currentItemData);
5555
offnum=ItemPointerGetOffsetNumber(current);
56+
_hash_checkpage(rel,buf,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
5657
page=BufferGetPage(buf);
57-
_hash_checkpage(rel,page,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
5858
hitem= (HashItem)PageGetItem(page,PageGetItemId(page,offnum));
5959
itup=&hitem->hash_itup;
6060
scan->xs_ctup.t_self=itup->t_tid;
@@ -77,8 +77,8 @@ _hash_readnext(Relation rel,
7777
if (BlockNumberIsValid(blkno))
7878
{
7979
*bufp=_hash_getbuf(rel,blkno,HASH_READ);
80+
_hash_checkpage(rel,*bufp,LH_OVERFLOW_PAGE);
8081
*pagep=BufferGetPage(*bufp);
81-
_hash_checkpage(rel,*pagep,LH_OVERFLOW_PAGE);
8282
*opaquep= (HashPageOpaque)PageGetSpecialPointer(*pagep);
8383
}
8484
}
@@ -98,8 +98,8 @@ _hash_readprev(Relation rel,
9898
if (BlockNumberIsValid(blkno))
9999
{
100100
*bufp=_hash_getbuf(rel,blkno,HASH_READ);
101+
_hash_checkpage(rel,*bufp,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
101102
*pagep=BufferGetPage(*bufp);
102-
_hash_checkpage(rel,*pagep,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
103103
*opaquep= (HashPageOpaque)PageGetSpecialPointer(*pagep);
104104
}
105105
}
@@ -168,8 +168,8 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
168168

169169
/* Read the metapage */
170170
metabuf=_hash_getbuf(rel,HASH_METAPAGE,HASH_READ);
171+
_hash_checkpage(rel,metabuf,LH_META_PAGE);
171172
metap= (HashMetaPage)BufferGetPage(metabuf);
172-
_hash_checkpage(rel, (Page)metap,LH_META_PAGE);
173173

174174
/*
175175
* Compute the target bucket number, and convert to block number.
@@ -198,8 +198,8 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
198198

199199
/* Fetch the primary bucket page for the bucket */
200200
buf=_hash_getbuf(rel,blkno,HASH_READ);
201+
_hash_checkpage(rel,buf,LH_BUCKET_PAGE);
201202
page=BufferGetPage(buf);
202-
_hash_checkpage(rel,page,LH_BUCKET_PAGE);
203203
opaque= (HashPageOpaque)PageGetSpecialPointer(page);
204204
Assert(opaque->hasho_bucket==bucket);
205205

@@ -216,8 +216,8 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
216216

217217
/* if we're here, _hash_step found a valid tuple */
218218
offnum=ItemPointerGetOffsetNumber(current);
219+
_hash_checkpage(rel,buf,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
219220
page=BufferGetPage(buf);
220-
_hash_checkpage(rel,page,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
221221
hitem= (HashItem)PageGetItem(page,PageGetItemId(page,offnum));
222222
itup=&hitem->hash_itup;
223223
scan->xs_ctup.t_self=itup->t_tid;
@@ -254,8 +254,8 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
254254
current=&(scan->currentItemData);
255255

256256
buf=*bufP;
257+
_hash_checkpage(rel,buf,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
257258
page=BufferGetPage(buf);
258-
_hash_checkpage(rel,page,LH_BUCKET_PAGE |LH_OVERFLOW_PAGE);
259259
opaque= (HashPageOpaque)PageGetSpecialPointer(page);
260260

261261
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp