Hi hackers,

I went looking at the other access methods and found a worse case than the
one I first reported, so here is a two-patch series.

0001 is what I sent before, unchanged: GiST, B-tree and hash page_items()
follow a line pointer after only checking ItemIdIsValid(), which just tests
that the pointer isn't NULL -- and it never is.

0002 is the new part.  Nothing checks the page header at all, and pd_lower
is what PageGetMaxOffsetNumber() is computed from, so two bytes are enough
to walk off the end of the line pointer array.


That includes heap_page_items() crash on a corrupt page:
    CREATE TABLE t AS SELECT i FROM generate_series(1,200) i;
    -- pd_lower is at offset 12
    SELECT 
heap_page_items(set_byte(set_byte(get_raw_page('t',0),12,255),13,255));
    ==ERROR: AddressSanitizer: heap-buffer-overflow READ of size 4
        #0 heap_page_items heapfuncs.c:188

So 0002 adds verify_page_header(), using the same checks PageIsVerified()
makes on the header.  I didn't call PageIsVerified() itself because it also
verifies the checksum, and there is no block number for a raw bytea; happy
to factor those checks into a shared helper instead, if that's preferred.
I also kept it out of get_page_from_raw(), so page_header() can still show
you have a damaged header.
While I was there, BRIN and GIN turned out to have the same problem as
0001, so 0002 fixes those too.

Thanks,
Shihao

Attachment: 0002-pageinspect-validate-page-headers-and-BRIN-and-GIN-p.patch
Description: Binary data

Attachment: 0001-pageinspect-validate-line-pointers-before-using-them.patch
Description: Binary data

Reply via email to