From: Alexander Korotkov Date: Wed, 22 May 2024 23:13:43 +0000 (+0300) Subject: amcheck: Report an error when the next page to a leaf is not a leaf X-Git-Tag: REL_17_BETA2~124 X-Git-Url: http://git.postgresql.org/gitweb/?a=commitdiff_plain;h=97e5b0026fc276ab1bcde58ae98ae1fcd9c3acc3;p=postgresql.git amcheck: Report an error when the next page to a leaf is not a leaf This is a very unlikely condition during checking a B-tree unique constraint, meaning that the index structure is violated badly, and we shouldn't continue checking to avoid endless loops, etc. So it's worth immediately throwing an error. Reported-by: Peter Geoghegan Discussion: https://postgr.es/m/CAH2-Wzk%2B2116uOXdOViA27SHcr31WKPgmjsxXLBs_aTxAeThzg%40mail.gmail.com Author: Pavel Borisov --- diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c index 5354b393b11..4347f9594c9 100644 --- a/contrib/amcheck/verify_nbtree.c +++ b/contrib/amcheck/verify_nbtree.c @@ -1831,7 +1831,6 @@ bt_target_page_check(BtreeCheckState *state) if (offset == max) { BTScanInsert rightkey; - BlockNumber rightblock_number; /* first offset on a right index page (log only) */ OffsetNumber rightfirstoffset = InvalidOffsetNumber; @@ -1876,10 +1875,11 @@ bt_target_page_check(BtreeCheckState *state) * If index has unique constraint make sure that no more than one * found equal items is visible. */ - rightblock_number = topaque->btpo_next; if (state->checkunique && state->indexinfo->ii_Unique && - rightkey && P_ISLEAF(topaque) && rightblock_number != P_NONE) + rightkey && P_ISLEAF(topaque) && !P_RIGHTMOST(topaque)) { + BlockNumber rightblock_number = topaque->btpo_next; + elog(DEBUG2, "check cross page unique condition"); /* @@ -1899,9 +1899,19 @@ bt_target_page_check(BtreeCheckState *state) rightblock_number); topaque = BTPageGetOpaque(rightpage); - if (P_IGNORE(topaque) || !P_ISLEAF(topaque)) - break; - + if (P_IGNORE(topaque)) + { + if (unlikely(!P_ISLEAF(topaque))) + ereport(ERROR, + (errcode(ERRCODE_INDEX_CORRUPTED), + errmsg("right block of leaf block is non-leaf for index \"%s\"", + RelationGetRelationName(state->rel)), + errdetail_internal("Block=%u page lsn=%X/%X.", + state->targetblock, + LSN_FORMAT_ARGS(state->targetlsn)))); + else + break; + } itemid = PageGetItemIdCareful(state, rightblock_number, rightpage, rightfirstoffset);