From 5d7eb3cc2e0fb36bc731dfe08b68068389cef4d5 Mon Sep 17 00:00:00 2001 From: Sehrope Sarkuni Date: Sun, 27 Sep 2026 12:48:04 +0000 Subject: [PATCH v1 1/7] gin: bound decode_varbyte() against the segment end decode_varbyte() had no end pointer and stopped only on a byte without the continuation bit set, so a corrupt stream ran past the segment. Pass the segment end in and stop at it, treating a truncated integer or one longer than the encoding can produce as corruption. The seven-way nesting becomes a loop. --- src/backend/access/gin/ginpostinglist.c | 56 +++++++------------------ 1 file changed, 15 insertions(+), 41 deletions(-) diff --git a/src/backend/access/gin/ginpostinglist.c b/src/backend/access/gin/ginpostinglist.c index 07656574029..89da084bbe8 100644 --- a/src/backend/access/gin/ginpostinglist.c +++ b/src/backend/access/gin/ginpostinglist.c @@ -130,51 +130,25 @@ encode_varbyte(uint64 val, unsigned char **ptr) * Decode varbyte-encoded integer at *ptr. *ptr is incremented to next integer. */ static uint64 -decode_varbyte(unsigned char **ptr) +decode_varbyte(unsigned char **ptr, unsigned char *endptr) { - uint64 val; + uint64 val = 0; unsigned char *p = *ptr; - uint64 c; - /* 1st byte */ - c = *(p++); - val = c & 0x7F; - if (c & 0x80) + for (int i = 0;; i++) { - /* 2nd byte */ + uint64 c; + + if (p >= endptr || i >= MaxBytesPerInteger) + ereport(ERROR, + (errcode(ERRCODE_DATA_CORRUPTED), + errmsg("corrupted GIN posting list"))); + c = *(p++); - val |= (c & 0x7F) << 7; - if (c & 0x80) - { - /* 3rd byte */ - c = *(p++); - val |= (c & 0x7F) << 14; - if (c & 0x80) - { - /* 4th byte */ - c = *(p++); - val |= (c & 0x7F) << 21; - if (c & 0x80) - { - /* 5th byte */ - c = *(p++); - val |= (c & 0x7F) << 28; - if (c & 0x80) - { - /* 6th byte */ - c = *(p++); - val |= (c & 0x7F) << 35; - if (c & 0x80) - { - /* 7th byte, should not have continuation bit */ - c = *(p++); - val |= c << 42; - Assert((c & 0x80) == 0); - } - } - } - } - } + val |= (c & 0x7F) << (7 * i); + + if ((c & 0x80) == 0) + break; } *ptr = p; @@ -338,7 +312,7 @@ ginPostingListDecodeAllSegments(GinPostingList *segment, int len, int *ndecoded_ result = repalloc_array(result, ItemPointerData, nallocated); } - val += decode_varbyte(&ptr); + val += decode_varbyte(&ptr, endptr); uint64_to_itemptr(val, &result[ndecoded]); ndecoded++; -- 2.17.1