]> git.ipfire.org Git - thirdparty/postgresql.git/commit
Fix GiST index-only scan column alignment issue.
authorPeter Geoghegan <pg@bowt.ie>
Fri, 17 Jul 2026 19:53:07 +0000 (15:53 -0400)
committerPeter Geoghegan <pg@bowt.ie>
Fri, 17 Jul 2026 19:53:07 +0000 (15:53 -0400)
commit1d4c81ad6266fb2e534fe2e6de8d0050041a4ad6
tree5fa264be9a959ca6e8bbebcbadd3f183ee646703
parent3601be26b3fa076e1aa03e9f1e0ad0e6077ce759
Fix GiST index-only scan column alignment issue.

An index-only scan filled its result slot from the HeapTuple an index AM
returns in scan->xs_hitup by deforming it with the virtual slot's own
tuple descriptor (during GiST and SP-GiST index-only scans).  But index
AMs form that heap tuple using their own descriptor, scan->xs_hitupdesc.
The AM's descriptor may disagree with the IoS virtual slot's descriptor
about each column's precise alignment, leading to "can't happen" errors
in certain rare edge cases.  Hard crashes were possible but much less
likely.

To fix, deform the tuple with the descriptor it was formed with.  This
is simpler, and makes xs_hitup handling (used by GiST and SP-GiST)
uniform with the nearby existing xs_itup handling (used by nbtree).

In practice this issue was very unlikely to be hit (it was found during
testing of a patch that will change the table AM API used during index
scans).  The only currently affected core opclass is GiST's range_ops.
It was only possible for the datum to be accessed at an incorrectly
aligned offset when reading the second or subsequent column from a
multicolumn GiST index.  This couldn't happen in the common case where
the datum used an unaligned short varlena header.  Moreover, an earlier
column had to leave the range datum at an offset where the two
alignments actually disagree (e.g., an odd-length varlena datum).

Author: Peter Geoghegan <pg@bowt.ie>
Reviewed-by: Tomas Vondra <tomas@vondra.me>
Discussion: https://postgr.es/m/CAH2-WzkGXa2SKnebdW29RT1hCcQBo_p03v3iqif2u9bjzLB-aQ@mail.gmail.com
Backpatch-through: 14
src/backend/executor/nodeIndexonlyscan.c
src/test/regress/expected/gist.out
src/test/regress/sql/gist.sql