From 439897dad9470f1836c18c75b409bc152483870f Mon Sep 17 00:00:00 2001 From: Ewan Young Date: Thu, 9 Jul 2026 00:42:19 +0800 Subject: [PATCH v2] Fix parallel GIN index build with keys larger than 65535 bytes During a parallel GIN build each key is serialized into a GinTuple, a transient representation used only while sorting. _gin_build_tuple() lays out the whole tuple -- the palloc size, the key memcpy, and the offset to the posting list -- from a local "int keylen". But the stored GinTuple.keylen field was uint16, so a key wider than 65535 bytes had its stored length silently truncated. On read-back, GinTupleGetFirst() and _gin_parse_tuple_items() recompute the posting-list offset from the truncated keylen and land inside the key data. ginPostingListDecodeAllSegments() then decodes garbage, tripping an assertion (or reading past the allocation in a non-assert build). Only parallel builds are affected, because only the parallel path materializes a GinTuple. Widen keylen so the stored length matches the length the rest of _gin_build_tuple() already computes. While here, make the type used for the key length consistent -- it was uint16 in GinTuple, Size in GinBuffer, and int in the _gin_build_tuple() local variable -- by using int throughout, matching the tuplen and nitems fields of GinTuple. Bug: #19545 Reported-by: Yuelin Wang <1217816127@qq.com> Discussion: https://postgr.es/m/19545-DUMMY-REPLACE-WITH-REAL-MSGID@postgresql.org --- src/backend/access/gin/gininsert.c | 2 +- src/include/access/gin_tuple.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c index cb9ed3b563c..01a7ef23372 100644 --- a/src/backend/access/gin/gininsert.c +++ b/src/backend/access/gin/gininsert.c @@ -1190,7 +1190,7 @@ typedef struct GinBuffer OffsetNumber attnum; GinNullCategory category; Datum key; /* 0 if no key (and keylen == 0) */ - Size keylen; /* number of bytes (not typlen) */ + int keylen; /* number of bytes (not typlen) */ /* type info */ int16 typlen; diff --git a/src/include/access/gin_tuple.h b/src/include/access/gin_tuple.h index 7bde05e2de4..9ca578652e7 100644 --- a/src/include/access/gin_tuple.h +++ b/src/include/access/gin_tuple.h @@ -23,7 +23,7 @@ typedef struct GinTuple { int tuplen; /* length of the whole tuple */ OffsetNumber attrnum; /* attnum of index key */ - uint16 keylen; /* bytes in data for key value */ + int keylen; /* bytes in data for key value */ int16 typlen; /* typlen for key */ bool typbyval; /* typbyval for key */ signed char category; /* category: normal or NULL? */ -- 2.47.3