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

Commit087771a

Browse files
committed
Add error checking to PageRepairFragmentation to ensure that it can
never overwrite adjacent pages with copied data, even if page headerand/or item pointers are already corrupt. Change inspired by troublereport from Alvaro Herrera.
1 parent453f350 commit087771a

File tree

1 file changed

+64
-41
lines changed

1 file changed

+64
-41
lines changed

‎src/backend/storage/page/bufpage.c

Lines changed: 64 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,15 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.37 2001/03/22 03:59:47 momjian Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/storage/page/bufpage.c,v 1.38 2001/10/23 02:20:15 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
15+
#include"postgres.h"
16+
1517
#include<sys/types.h>
1618
#include<sys/file.h>
1719

18-
#include"postgres.h"
19-
2020
#include"storage/bufpage.h"
2121

2222

@@ -38,12 +38,12 @@ PageInit(Page page, Size pageSize, Size specialSize)
3838
{
3939
PageHeaderp= (PageHeader)page;
4040

41+
specialSize=MAXALIGN(specialSize);
42+
4143
Assert(pageSize==BLCKSZ);
4244
Assert(pageSize>
4345
specialSize+sizeof(PageHeaderData)-sizeof(ItemIdData));
4446

45-
specialSize=MAXALIGN(specialSize);
46-
4747
p->pd_lower=sizeof(PageHeaderData)-sizeof(ItemIdData);
4848
p->pd_upper=pageSize-specialSize;
4949
p->pd_special=pageSize-specialSize;
@@ -93,7 +93,7 @@ PageAddItem(Page page,
9393
ItemIditemId;
9494
OffsetNumberlimit;
9595
boolneedshuffle= false;
96-
booloverwritemode=flags&OverwritePageMode;
96+
booloverwritemode=(flags&OverwritePageMode)!=0;
9797

9898
flags &= ~OverwritePageMode;
9999

@@ -209,7 +209,7 @@ PageGetTempPage(Page page, Size specialSize)
209209
thdr= (PageHeader)temp;
210210

211211
/* copy old page in */
212-
memmove(temp,page,pageSize);
212+
memcpy(temp,page,pageSize);
213213

214214
/* clear out the middle */
215215
size= (pageSize-sizeof(PageHeaderData))+sizeof(ItemIdData);
@@ -239,27 +239,22 @@ PageRestoreTempPage(Page tempPage, Page oldPage)
239239
pfree(tempPage);
240240
}
241241

242-
/* ----------------
243-
*itemid stuff for PageRepairFragmentation
244-
* ----------------
242+
/*
243+
* sorting support for PageRepairFragmentation
245244
*/
246245
structitemIdSortData
247246
{
248247
intoffsetindex;/* linp array index */
249-
ItemIdDataitemiddata;
248+
intitemoff;/* page offset of item data */
249+
Sizealignedlen;/* MAXALIGN(item data len) */
250250
};
251251

252252
staticint
253-
itemidcompare(constvoid*itemidp1,constvoid*itemidp2)
253+
itemoffcompare(constvoid*itemidp1,constvoid*itemidp2)
254254
{
255-
if (((structitemIdSortData*)itemidp1)->itemiddata.lp_off==
256-
((structitemIdSortData*)itemidp2)->itemiddata.lp_off)
257-
return0;
258-
elseif (((structitemIdSortData*)itemidp1)->itemiddata.lp_off<
259-
((structitemIdSortData*)itemidp2)->itemiddata.lp_off)
260-
return1;
261-
else
262-
return-1;
255+
/* Sort in decreasing itemoff order */
256+
return ((structitemIdSortData*)itemidp2)->itemoff-
257+
((structitemIdSortData*)itemidp1)->itemoff;
263258
}
264259

265260
/*
@@ -269,20 +264,40 @@ itemidcompare(const void *itemidp1, const void *itemidp2)
269264
* It doesn't remove unused line pointers! Please don't change this.
270265
* This routine is usable for heap pages only.
271266
*
267+
* Returns number of unused line pointers on page. If "unused" is not NULL
268+
* then the unused[] array is filled with indexes of unused line pointers.
272269
*/
273270
int
274271
PageRepairFragmentation(Pagepage,OffsetNumber*unused)
275272
{
276-
inti;
273+
Offsetpd_lower= ((PageHeader)page)->pd_lower;
274+
Offsetpd_upper= ((PageHeader)page)->pd_upper;
275+
Offsetpd_special= ((PageHeader)page)->pd_special;
277276
structitemIdSortData*itemidbase,
278277
*itemidptr;
279278
ItemIdlp;
280279
intnline,
281280
nused;
281+
inti;
282+
Sizetotallen;
282283
Offsetupper;
283-
SizealignedSize;
284284

285-
nline= (int16)PageGetMaxOffsetNumber(page);
285+
/*
286+
* It's worth the trouble to be more paranoid here than in most places,
287+
* because we are about to reshuffle data in (what is usually) a shared
288+
* disk buffer. If we aren't careful then corrupted pointers, lengths,
289+
* etc could cause us to clobber adjacent disk buffers, spreading the
290+
* data loss further. So, check everything.
291+
*/
292+
if (pd_lower< (sizeof(PageHeaderData)-sizeof(ItemIdData))||
293+
pd_lower>pd_upper||
294+
pd_upper>pd_special||
295+
pd_special>BLCKSZ||
296+
pd_special!=MAXALIGN(pd_special))
297+
elog(ERROR,"PageRepairFragmentation: corrupted page pointers: lower = %u, upper = %u, special = %u",
298+
pd_lower,pd_upper,pd_special);
299+
300+
nline=PageGetMaxOffsetNumber(page);
286301
nused=0;
287302
for (i=0;i<nline;i++)
288303
{
@@ -297,56 +312,65 @@ PageRepairFragmentation(Page page, OffsetNumber *unused)
297312

298313
if (nused==0)
299314
{
315+
/* Page is completely empty, so just reset it quickly */
300316
for (i=0;i<nline;i++)
301317
{
302318
lp= ((PageHeader)page)->pd_linp+i;
303-
if ((*lp).lp_len>0)/* unused, but allocated */
304-
(*lp).lp_len=0;/* indicate unused & deallocated */
319+
(*lp).lp_len=0;/* indicate unused & deallocated */
305320
}
306-
307-
((PageHeader)page)->pd_upper= ((PageHeader)page)->pd_special;
321+
((PageHeader)page)->pd_upper=pd_special;
308322
}
309323
else
310324
{/* nused != 0 */
325+
/* Need to compact the page the hard way */
311326
itemidbase= (structitemIdSortData*)
312327
palloc(sizeof(structitemIdSortData)*nused);
313-
MemSet((char*)itemidbase,0,sizeof(structitemIdSortData)*nused);
314328
itemidptr=itemidbase;
329+
totallen=0;
315330
for (i=0;i<nline;i++)
316331
{
317332
lp= ((PageHeader)page)->pd_linp+i;
318333
if ((*lp).lp_flags&LP_USED)
319334
{
320335
itemidptr->offsetindex=i;
321-
itemidptr->itemiddata=*lp;
336+
itemidptr->itemoff= (*lp).lp_off;
337+
if (itemidptr->itemoff< (int)pd_upper||
338+
itemidptr->itemoff >= (int)pd_special)
339+
elog(ERROR,"PageRepairFragmentation: corrupted item pointer %u",
340+
itemidptr->itemoff);
341+
itemidptr->alignedlen=MAXALIGN((*lp).lp_len);
342+
totallen+=itemidptr->alignedlen;
322343
itemidptr++;
323344
}
324345
else
325346
{
326-
if ((*lp).lp_len>0)/* unused, but allocated */
327-
(*lp).lp_len=0;/* indicate unused & deallocated */
347+
(*lp).lp_len=0;/* indicate unused & deallocated */
328348
}
329349
}
330350

331-
/* sort itemIdSortData array... */
351+
if (totallen> (Size) (pd_special-pd_lower))
352+
elog(ERROR,"PageRepairFragmentation: corrupted item lengths, total %u, avail %u",
353+
totallen,pd_special-pd_lower);
354+
355+
/* sort itemIdSortData array into decreasing itemoff order */
332356
qsort((char*)itemidbase,nused,sizeof(structitemIdSortData),
333-
itemidcompare);
357+
itemoffcompare);
334358

335359
/* compactify page */
336-
((PageHeader)page)->pd_upper= ((PageHeader)page)->pd_special;
360+
upper=pd_special;
337361

338362
for (i=0,itemidptr=itemidbase;i<nused;i++,itemidptr++)
339363
{
340364
lp= ((PageHeader)page)->pd_linp+itemidptr->offsetindex;
341-
alignedSize=MAXALIGN((*lp).lp_len);
342-
upper= ((PageHeader)page)->pd_upper-alignedSize;
365+
upper-=itemidptr->alignedlen;
343366
memmove((char*)page+upper,
344-
(char*)page+(*lp).lp_off,
345-
(*lp).lp_len);
367+
(char*)page+itemidptr->itemoff,
368+
itemidptr->alignedlen);
346369
(*lp).lp_off=upper;
347-
((PageHeader)page)->pd_upper=upper;
348370
}
349371

372+
((PageHeader)page)->pd_upper=upper;
373+
350374
pfree(itemidbase);
351375
}
352376

@@ -362,12 +386,11 @@ PageGetFreeSpace(Page page)
362386
{
363387
Sizespace;
364388

365-
366389
space= ((PageHeader)page)->pd_upper- ((PageHeader)page)->pd_lower;
367390

368391
if (space<sizeof(ItemIdData))
369392
return0;
370-
space-=sizeof(ItemIdData);/* XXX not alwaystrue */
393+
space-=sizeof(ItemIdData);/* XXX not alwaysappropriate */
371394

372395
returnspace;
373396
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp