Skip to content

Commit 80d5e3a

Browse files
committed
amcheck: Tighten up validation of redirect line pointers.
Commit bbc1376 added a new lp_valid[] array which records whether or not a line pointer was thought to be valid, but entries could sometimes get set to true in cases where that wasn't actually safe. Fix that. Suppose A is a redirect line pointer and B is the other line pointer to which it points. The old code could mishandle this situation in a couple of different ways. First, if B was unused, we'd complain about corruption but still set lp_valid[A] = true, causing later code to try to access the B as if it were pointing to a tuple. Second, if B was dead, we wouldn't complain about corruption at all, which is an oversight, and would also set lp_valid[A] = true, which would again confuse later code. Fix all that. In the case where B is a redirect, the old code was correct, but refactor things a bit anyway so that all of these cases are handled more symmetrically. Also add an Assert() and some comments. Andres Freund and Robert Haas Discussion: http://postgr.es/m/20230323172607.y3lejpntjnuis5vv%40awork3.anarazel.de
1 parent 5a91c79 commit 80d5e3a

File tree

1 file changed

+31
-9
lines changed

1 file changed

+31
-9
lines changed

contrib/amcheck/verify_heapam.c

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -481,11 +481,35 @@ verify_heapam(PG_FUNCTION_ARGS)
481481
(unsigned) maxoff));
482482
continue;
483483
}
484+
485+
/*
486+
* Since we've checked that this redirect points to a line
487+
* pointer between FirstOffsetNumber and maxoff, it should
488+
* now be safe to fetch the referenced line pointer. We expect
489+
* it to be LP_NORMAL; if not, that's corruption.
490+
*/
484491
rditem = PageGetItemId(ctx.page, rdoffnum);
485492
if (!ItemIdIsUsed(rditem))
493+
{
486494
report_corruption(&ctx,
487-
psprintf("line pointer redirection to unused item at offset %u",
495+
psprintf("redirected line pointer points to an unused item at offset %u",
488496
(unsigned) rdoffnum));
497+
continue;
498+
}
499+
else if (ItemIdIsDead(rditem))
500+
{
501+
report_corruption(&ctx,
502+
psprintf("redirected line pointer points to a dead item at offset %u",
503+
(unsigned) rdoffnum));
504+
continue;
505+
}
506+
else if (ItemIdIsRedirected(rditem))
507+
{
508+
report_corruption(&ctx,
509+
psprintf("redirected line pointer points to another redirected line pointer at offset %u",
510+
(unsigned) rdoffnum));
511+
continue;
512+
}
489513

490514
/*
491515
* Record the fact that this line pointer has passed basic
@@ -584,14 +608,12 @@ verify_heapam(PG_FUNCTION_ARGS)
584608
/* Handle the cases where the current line pointer is a redirect. */
585609
if (ItemIdIsRedirected(curr_lp))
586610
{
587-
/* Can't redirect to another redirect. */
588-
if (ItemIdIsRedirected(next_lp))
589-
{
590-
report_corruption(&ctx,
591-
psprintf("redirected line pointer points to another redirected line pointer at offset %u",
592-
(unsigned) nextoffnum));
593-
continue;
594-
}
611+
/*
612+
* We should not have set successor[ctx.offnum] to a value
613+
* other than InvalidOffsetNumber unless that line pointer
614+
* is LP_NORMAL.
615+
*/
616+
Assert(ItemIdIsNormal(next_lp));
595617

596618
/* Can only redirect to a HOT tuple. */
597619
next_htup = (HeapTupleHeader) PageGetItem(ctx.page, next_lp);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy