Thread

Commits

  1. Remove btree_gist's useless logic for encoding-aware truncation.

  2. Tighten up btree_gist's handling of truncated bounds.

  3. Sync signatures of gbt_var_consistent() and gbt_num_consistent().

  4. Fix btree_gist's NotEqual strategy on internal index pages.

  5. Reverse-engineer some documentation for btree_gist's varlena modules.

  6. Use the proper comparator in gbt_bit_ssup_cmp.

  1. Fw:Re: Fw: gbt_var_consistent in contrib/btree_gist/btree_utils_var.c has internal-node type confusion on the <> strategy, bypassing exclusion constraints

    王跃林 <violin0613@tju.edu.cn> — 2026-06-16T11:29:35Z

    
    
    
    
    
    
    
     王跃林
    3020001251@tju.edu.cn
    
    
    
    
    
    
    
    
    
    
    Forwarded message:
    From:Noah Misch <noah@leadboat.com>Date:2026-06-13 08:29:28(中国 (GMT+08:00))To:王跃林<violin0613@tju.edu.cn>Cc:security <security@postgresql.org>Subject:Re: Fw: gbt_var_consistent in contrib/btree_gist/btree_utils_var.c has internal-node type confusion on the <> strategy, bypassing exclusion constraintsOn Mon, Jun 08, 2026 at 11:24:02PM +0800, 王跃林 wrote:
    > gbt_var_node_truncate (btree_utils_var.c:214) truncates internal node keys to a common-prefix length. The resulting bytea can have VARSIZE anywhere from 4 upward. When the truncated VARSIZE is below 8 and that key reaches bit_cmp via the buggy BtreeGistNotEqual branch, bytelen becomes negative. Passed to memcmp as size_t, that is several GB. ASan catches it as negative-size-param. A production build without ASan will eventually SEGV when the read crosses an unmapped page.
    
    Got it.  That doesn't qualify as a vuln per
    https://www.postgresql.org/support/security/:
    
      The PostgreSQL Security Team typically does not consider a denial-of-service
      on a PostgreSQL server from an authenticated, valid SQL statement to be a
      security vulnerability. A denial-of-service issue of this nature could still
      be a bug, and we encourage you to report it on the Report a Bug page.
    
    If nobody objects by 2026-06-16T00:00+0000, please report the bug to
    pgsql-bugs@postgresql.org.
    
    
    
    
  2. Re: Fw:Re: Fw: gbt_var_consistent in contrib/btree_gist/btree_utils_var.c has internal-node type confusion on the <> strategy, bypassing exclusion constraints

    Ayush Tiwari <ayushtiwari.slg01@gmail.com> — 2026-06-17T19:19:03Z

    Hi,
    
    On Tue, 16 Jun 2026 at 16:59, 王跃林 <violin0613@tju.edu.cn> wrote:
    
    > 0800, 王跃林 wrote:
    >
    > > gbt_var_node_truncate (btree_utils_var.c:214) truncates internal node keys to a common-prefix length. The resulting bytea can have VARSIZE anywhere from 4 upward. When the truncated VARSIZE is below 8 and that key reaches bit_cmp via the buggy BtreeGistNotEqual branch, bytelen becomes negative. Passed to memcmp as size_t, that is several GB. ASan catches it as negative-size-param. A production build without ASan will eventually SEGV when the read crosses an unmapped page.
    >
    > Thanks for the report!
    
    In gbt_var_consistent() (contrib/btree_gist/btree_utils_var.c), the <>
    (BtreeGistNotEqual) branch is the only strategy that does not distinguish
    leaf from internal pages. It applies the type's equality function directly
    to the stored key on both bounds:
    
      retval = !(tinfo->f_eq(query, key->lower, ...) &&
               tinfo->f_eq(query, key->upper, ...));
    
    That seems to be the problem: on internal pages those keys are
    truncated (and for bit/varbit the length header is gone too), so
    they aren't really valid values to hand to the type's equality
    function.  Hence the negative length reaching memcmp().
    
    Would it make sense to just have <> follow the same leaf-vs-internal
    pattern as the other strategies; negate equality on a leaf, and
    otherwise recurse?  An internal page can always contain some
    non-equal value, so I don't think we lose anything by descending.
    I put together a small patch along those lines (plus a bit(8) test
    that goes through internal pages); it's attached if it's useful.
    (PS. The test exercises the path but passes on a plain build; the OOB
    read shows up under ASan (negative-size-param).)
    
    I didn't touch the fixed-size path in btree_utils_num.c, since its
    internal keys look like they're exact lower/upper values, but
    please correct me if I'm missing something there.
    
    Regards,
    Ayush
    
  3. Re: Fw:Re: Fw: gbt_var_consistent in contrib/btree_gist/btree_utils_var.c has internal-node type confusion on the <> strategy, bypassing exclusion constraints

    王跃林 <violin0613@tju.edu.cn> — 2026-06-18T05:24:05Z

    
    The analysis and fix look correct. The BtreeGistNotEqual branch is the only strategy that bypasses the is_leaf check and passes potentially truncated internal-node keys directly to f_eq, which is unsafe for types like bit and varbit that require a minimum valid header size. Returning true for internal nodes is the right conservative choice and is consistent with how the other strategies handle the internal-node case.
    
    
    
    
    
     王跃林
    3020001251@tju.edu.cn
    
    
    
    
    
    
    
    
    
    
    
    Original:
    From:Ayush Tiwari <ayushtiwari.slg01@gmail.com>Date:2026-06-18 03:19:03(中国 (GMT+08:00))To:王跃林<violin0613@tju.edu.cn>Cc:pgsql-bugs <pgsql-bugs@postgresql.org>Subject:Re: Fw:Re: Fw: gbt_var_consistent in contrib/btree_gist/btree_utils_var.c has internal-node type confusion on the <> strategy, bypassing exclusion constraintsHi,
    
    On Tue, 16 Jun 2026 at 16:59, 王跃林 <violin0613@tju.edu.cn> wrote:
    
    0800, 王跃林 wrote:
    > gbt_var_node_truncate (btree_utils_var.c:214) truncates internal node keys to a common-prefix length. The resulting bytea can have VARSIZE anywhere from 4 upward. When the truncated VARSIZE is below 8 and that key reaches bit_cmp via the buggy BtreeGistNotEqual branch, bytelen becomes negative. Passed to memcmp as size_t, that is several GB. ASan catches it as negative-size-param. A production build without ASan will eventually SEGV when the read crosses an unmapped page.
    
    
    Thanks for the report!
    
    In gbt_var_consistent() (contrib/btree_gist/btree_utils_var.c), the <>
    (BtreeGistNotEqual) branch is the only strategy that does not distinguish
    leaf from internal pages. It applies the type's equality function directly
    to the stored key on both bounds:
    
      retval = !(tinfo->f_eq(query, key->lower, ...) &&
               tinfo->f_eq(query, key->upper, ...));
    
    That seems to be the problem: on internal pages those keys are
    truncated (and for bit/varbit the length header is gone too), so
    they aren't really valid values to hand to the type's equality
    function.  Hence the negative length reaching memcmp().
    
    
    Would it make sense to just have <> follow the same leaf-vs-internal
    pattern as the other strategies; negate equality on a leaf, and
    otherwise recurse?  An internal page can always contain some
    non-equal value, so I don't think we lose anything by descending.
    I put together a small patch along those lines (plus a bit(8) test
    that goes through internal pages); it's attached if it's useful.
    (PS. The test exercises the path but passes on a plain build; the OOB
    read shows up under ASan (negative-size-param).)
    
    I didn't touch the fixed-size path in btree_utils_num.c, since its
    internal keys look like they're exact lower/upper values, but
    please correct me if I'm missing something there.
    
    Regards,
    Ayush