1
0
mirror of https://github.com/postgres/postgres.git synced 2025-12-18 05:01:01 +03:00

Add offnum range checks to suppress compile warnings with UBSAN.

Late-model gcc with -fsanitize=undefined enabled issues warnings
about uses of PageGetItemId() when it can't prove that the
offsetNumber is > 0.  The call sites where this happens are
checking that the offnum is <= PageGetMaxOffsetNumber(page), so
it seems reasonable to add an explicit check that offnum >= 1 too.

While at it, rearrange the code to be less contorted and avoid
duplicate checks on PageGetMaxOffsetNumber.  Maybe the compiler
would optimize away the duplicate logic or maybe not, but the
existing coding has little to recommend it anyway.

There are multiple instances of this identical coding pattern in
heapam.c and heapam_xlog.c.  Current gcc only complains about two
of them, but I fixed them all in the name of consistency.

Potentially this could be back-patched in the name of silencing
warnings; but I think enabling UBSAN is mainly something people
would do on HEAD, so for now it seems not worth the trouble.

Discussion: https://postgr.es/m/1699806.1765746897@sss.pgh.pa.us
This commit is contained in:
Tom Lane
2025-12-15 12:40:09 -05:00
parent bd43940b02
commit 8191937082
3 changed files with 38 additions and 35 deletions

View File

@@ -6116,7 +6116,7 @@ heap_finish_speculative(Relation relation, const ItemPointerData *tid)
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
ItemId lp = NULL; ItemId lp;
HeapTupleHeader htup; HeapTupleHeader htup;
buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid)); buffer = ReadBuffer(relation, ItemPointerGetBlockNumber(tid));
@@ -6124,10 +6124,10 @@ heap_finish_speculative(Relation relation, const ItemPointerData *tid)
page = BufferGetPage(buffer); page = BufferGetPage(buffer);
offnum = ItemPointerGetOffsetNumber(tid); offnum = ItemPointerGetOffsetNumber(tid);
if (PageGetMaxOffsetNumber(page) >= offnum) if (offnum < 1 || offnum > PageGetMaxOffsetNumber(page))
elog(ERROR, "offnum out of range");
lp = PageGetItemId(page, offnum); lp = PageGetItemId(page, offnum);
if (!ItemIdIsNormal(lp))
if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(ERROR, "invalid lp"); elog(ERROR, "invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp); htup = (HeapTupleHeader) PageGetItem(page, lp);

View File

@@ -422,7 +422,7 @@ heap_xlog_delete(XLogReaderState *record)
xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record); xl_heap_delete *xlrec = (xl_heap_delete *) XLogRecGetData(record);
Buffer buffer; Buffer buffer;
Page page; Page page;
ItemId lp = NULL; ItemId lp;
HeapTupleHeader htup; HeapTupleHeader htup;
BlockNumber blkno; BlockNumber blkno;
RelFileLocator target_locator; RelFileLocator target_locator;
@@ -451,10 +451,10 @@ heap_xlog_delete(XLogReaderState *record)
{ {
page = BufferGetPage(buffer); page = BufferGetPage(buffer);
if (PageGetMaxOffsetNumber(page) >= xlrec->offnum) if (xlrec->offnum < 1 || xlrec->offnum > PageGetMaxOffsetNumber(page))
elog(PANIC, "offnum out of range");
lp = PageGetItemId(page, xlrec->offnum); lp = PageGetItemId(page, xlrec->offnum);
if (!ItemIdIsNormal(lp))
if (PageGetMaxOffsetNumber(page) < xlrec->offnum || !ItemIdIsNormal(lp))
elog(PANIC, "invalid lp"); elog(PANIC, "invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp); htup = (HeapTupleHeader) PageGetItem(page, lp);
@@ -817,7 +817,7 @@ heap_xlog_update(XLogReaderState *record, bool hot_update)
nbuffer; nbuffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
ItemId lp = NULL; ItemId lp;
HeapTupleData oldtup; HeapTupleData oldtup;
HeapTupleHeader htup; HeapTupleHeader htup;
uint16 prefixlen = 0, uint16 prefixlen = 0,
@@ -881,10 +881,10 @@ heap_xlog_update(XLogReaderState *record, bool hot_update)
{ {
page = BufferGetPage(obuffer); page = BufferGetPage(obuffer);
offnum = xlrec->old_offnum; offnum = xlrec->old_offnum;
if (PageGetMaxOffsetNumber(page) >= offnum) if (offnum < 1 || offnum > PageGetMaxOffsetNumber(page))
elog(PANIC, "offnum out of range");
lp = PageGetItemId(page, offnum); lp = PageGetItemId(page, offnum);
if (!ItemIdIsNormal(lp))
if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(PANIC, "invalid lp"); elog(PANIC, "invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp); htup = (HeapTupleHeader) PageGetItem(page, lp);
@@ -1087,7 +1087,7 @@ heap_xlog_confirm(XLogReaderState *record)
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
ItemId lp = NULL; ItemId lp;
HeapTupleHeader htup; HeapTupleHeader htup;
if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO) if (XLogReadBufferForRedo(record, 0, &buffer) == BLK_NEEDS_REDO)
@@ -1095,10 +1095,10 @@ heap_xlog_confirm(XLogReaderState *record)
page = BufferGetPage(buffer); page = BufferGetPage(buffer);
offnum = xlrec->offnum; offnum = xlrec->offnum;
if (PageGetMaxOffsetNumber(page) >= offnum) if (offnum < 1 || offnum > PageGetMaxOffsetNumber(page))
elog(PANIC, "offnum out of range");
lp = PageGetItemId(page, offnum); lp = PageGetItemId(page, offnum);
if (!ItemIdIsNormal(lp))
if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(PANIC, "invalid lp"); elog(PANIC, "invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp); htup = (HeapTupleHeader) PageGetItem(page, lp);
@@ -1126,7 +1126,7 @@ heap_xlog_lock(XLogReaderState *record)
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
ItemId lp = NULL; ItemId lp;
HeapTupleHeader htup; HeapTupleHeader htup;
/* /*
@@ -1155,10 +1155,10 @@ heap_xlog_lock(XLogReaderState *record)
page = BufferGetPage(buffer); page = BufferGetPage(buffer);
offnum = xlrec->offnum; offnum = xlrec->offnum;
if (PageGetMaxOffsetNumber(page) >= offnum) if (offnum < 1 || offnum > PageGetMaxOffsetNumber(page))
elog(PANIC, "offnum out of range");
lp = PageGetItemId(page, offnum); lp = PageGetItemId(page, offnum);
if (!ItemIdIsNormal(lp))
if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(PANIC, "invalid lp"); elog(PANIC, "invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp); htup = (HeapTupleHeader) PageGetItem(page, lp);
@@ -1200,7 +1200,7 @@ heap_xlog_lock_updated(XLogReaderState *record)
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
ItemId lp = NULL; ItemId lp;
HeapTupleHeader htup; HeapTupleHeader htup;
xlrec = (xl_heap_lock_updated *) XLogRecGetData(record); xlrec = (xl_heap_lock_updated *) XLogRecGetData(record);
@@ -1231,10 +1231,10 @@ heap_xlog_lock_updated(XLogReaderState *record)
page = BufferGetPage(buffer); page = BufferGetPage(buffer);
offnum = xlrec->offnum; offnum = xlrec->offnum;
if (PageGetMaxOffsetNumber(page) >= offnum) if (offnum < 1 || offnum > PageGetMaxOffsetNumber(page))
elog(PANIC, "offnum out of range");
lp = PageGetItemId(page, offnum); lp = PageGetItemId(page, offnum);
if (!ItemIdIsNormal(lp))
if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(PANIC, "invalid lp"); elog(PANIC, "invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp); htup = (HeapTupleHeader) PageGetItem(page, lp);
@@ -1263,7 +1263,7 @@ heap_xlog_inplace(XLogReaderState *record)
Buffer buffer; Buffer buffer;
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
ItemId lp = NULL; ItemId lp;
HeapTupleHeader htup; HeapTupleHeader htup;
uint32 oldlen; uint32 oldlen;
Size newlen; Size newlen;
@@ -1275,10 +1275,10 @@ heap_xlog_inplace(XLogReaderState *record)
page = BufferGetPage(buffer); page = BufferGetPage(buffer);
offnum = xlrec->offnum; offnum = xlrec->offnum;
if (PageGetMaxOffsetNumber(page) >= offnum) if (offnum < 1 || offnum > PageGetMaxOffsetNumber(page))
elog(PANIC, "offnum out of range");
lp = PageGetItemId(page, offnum); lp = PageGetItemId(page, offnum);
if (!ItemIdIsNormal(lp))
if (PageGetMaxOffsetNumber(page) < offnum || !ItemIdIsNormal(lp))
elog(PANIC, "invalid lp"); elog(PANIC, "invalid lp");
htup = (HeapTupleHeader) PageGetItem(page, lp); htup = (HeapTupleHeader) PageGetItem(page, lp);

View File

@@ -2148,6 +2148,9 @@ _bt_get_endpoint(Relation rel, uint32 level, bool rightmost)
else else
offnum = P_FIRSTDATAKEY(opaque); offnum = P_FIRSTDATAKEY(opaque);
if (offnum < 1 || offnum > PageGetMaxOffsetNumber(page))
elog(PANIC, "offnum out of range");
itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum)); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, offnum));
blkno = BTreeTupleGetDownLink(itup); blkno = BTreeTupleGetDownLink(itup);