| From: | PG Bug reporting form <noreply(at)postgresql(dot)org> |
|---|---|
| To: | pgsql-bugs(at)lists(dot)postgresql(dot)org |
| Cc: | wf13934952799(at)gmail(dot)com |
| Subject: | BUG #19829: BTREE pivot tuple length overflows t_info when BLCKSZ=32768 |
| Date: | 2026-11-03 07:46:52 |
| Message-ID: | 19829-5d18cdf4d4dd6844@postgresql.org |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
The following bug has been logged on the website:
Bug reference: 19829
Logged by: wangfei
Email address: wf13934952799(at)gmail(dot)com
PostgreSQL version: 18.6
Operating system: ubuntu-24.04
Description:
PostgreSQL version: 19devel (also reproducible on 18.x)
Operating system: Linux x86_64
Configure options: --with-blocksize=32
With BLCKSZ=32768, BTMaxItemSize() evaluates to roughly 10896 bytes, but the
tuple length field reserved by INDEX_SIZE_MASK in IndexTupleData.t_info can
only represent 8191 bytes. index_form_tuple() enforces the 8191 limit, so a
leaf tuple is at most 8184 bytes after MAXALIGN. _bt_truncate() may then
need
to append a tiebreaker heap TID:
newsize = MAXALIGN(IndexTupleSize(pivot)) +
MAXALIGN(sizeof(ItemPointerData));
...
tidpivot->t_info &= ~INDEX_SIZE_MASK;
tidpivot->t_info |= newsize;
For a maximally sized leaf tuple this is 8184 + 8 = 8192, i.e. exactly
INDEX_SIZE_MASK + 1, so the length field wraps to zero. The result is a
zero-length pivot tuple used as a leaf high key; PageAddItem() and
XLogRegisterBufData() both accept it without complaint, so the corruption is
written out and WAL-logged silently.
BTMaxItemSize() is supposed to keep leaf tuples small enough that this
cannot
happen, but the one-third-of-a-page rule scales with BLCKSZ while
INDEX_SIZE_MASK does not, so at BLCKSZ=32768 the one-third rule is no longer
the binding constraint. Block sizes of 16384 and below are unaffected.
Steps to reproduce:
< SQL 脚本>
Expected: either the insert is rejected, or the pivot tuple is stored
correctly.
Actual: high key with length 0 (amcheck reports: <具体报错>).
A patch against master is attached. It takes Min() of the one-third rule
and
what t_info can represent in BTMaxItemSize(), and adds a defensive
elog(ERROR)
in _bt_truncate() so that a future miscalculation cannot corrupt an index
silently. Since index_form_tuple() already caps index tuples at 8184 bytes,
lowering the BLCKSZ=32768 limit cannot invalidate any index that could
actually exist on disk, so there is no on-disk compatibility concern.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | 王飞 | 2026-11-03 08:10:18 | Re: BUG #19829: BTREE pivot tuple length overflows t_info when BLCKSZ=32768 |
| Previous Message | Gowdham M | 2026-11-03 06:50:33 | Re: [Bug] Heap use-after-free in COPY FROM error context after ON_ERROR ignore skips a row |