Re: [BUG] hstore integer overflow when constructing large values

From: Keyerror Smart <smartkeyerror(at)gmail(dot)com>
To: Tender Wang <tndrwang(at)gmail(dot)com>
Cc: PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org>
Subject: Re: [BUG] hstore integer overflow when constructing large values
Date: 2026-08-15 06:52:48
Message-ID: CAD=-kXbxFSNOrj4m3UYxRckzkaOUtxxzdKZnmSCmsbq3CcUdqQ@mail.gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

On Sat, Aug 15, 2026 at 11:06 AM Tender Wang <tndrwang(at)gmail(dot)com> wrote:
> The attached patch checks the accumulated length before updating `buflen`,
> so that an oversized hstore is rejected before the `int32` overflow can
> occur. It also checks the complete size calculated by `CALCDATASIZE()`,
> since the HEntry array and hstore header must fit in the resulting datum
as
> well.

Hi,

I applied the patch and it applies cleanly on master, compiles without
warnings, and the hstore regression tests pass.

A minor comments:

The error message could be more informative, following the jsonb
precedent ("total size of jsonb array elements exceeds the maximum of
%u bytes"). Something like:

errmsg("total size of hstore data exceeds the maximum of %zu bytes",
(Size) MaxAllocSize)

I agree that a regression test isn't practical here, since triggering
the overflow requires more than 2GB of input; that's consistent with
the existing limits (e.g. HSTORE_MAX_KEY_LEN) not being exercised in
the tests either.

Tender Wang <tndrwang(at)gmail(dot)com> 于2026年8月15日周六 11:20写道:

> Hi,
>
> My colleague Man Zeng reported an issue where hstore could fail with a
> very large and unexpected memory allocation request. I investigated the
> issue and found an integer overflow when constructing an hstore from
> multiple large values.
>
> For example:
>
> CREATE EXTENSION hstore;
> CREATE TABLE t(a text, b text, c text);
>
> INSERT INTO t VALUES (repeat('x', 720000000), NULL, NULL);
> UPDATE t SET b = repeat('y', 720000000);
> UPDATE t SET c = repeat('z', 720000000);
>
> SELECT hstore(t) FROM t;
>
> This produces:
> ERROR: invalid memory alloc request size 18446744071574584355
>
> The problem is in `hstoreUniquePairs()`. `buflen` is an `int32`, and the
> total length of all keys and values is accumulated into it without an
> overflow check:
>
> *buflen += res->keylen + ((res->isnull) ? 0 : res->vallen);
>
> Each individual value in the example is within the hstore value length
> limit, but their combined length is not. In this case, the accumulated
> length is:
> (720000000 + 1) * 3 = 2160000003
>
> which exceeds `INT_MAX`. `buflen` therefore overflows before
> `hstorePairs()` calculates the size of the resulting hstore. The negative
> value eventually gets converted to `Size` when passed to `palloc()`,
> resulting in the very large allocation size shown in the error message.
>
> The attached patch checks the accumulated length before updating `buflen`,
> so that an oversized hstore is rejected before the `int32` overflow can
> occur. It also checks the complete size calculated by `CALCDATASIZE()`,
> since the HEntry array and hstore header must fit in the resulting datum as
> well.
>
> I kept the existing `int32` arguments of `hstoreUniquePairs()` and
> `hstorePairs()` unchanged rather than changing the exported interfaces.
>
> The patch reports the size limit error consistently with the existing
> hstore length checks.
>
> I have not added the reproducer to the regression tests because it requires
> constructing more than 2GB of input data. I couldn't find a reasonably
> small SQL-level test case that exercises the same overflow.
>
> Thanks to Man Zeng for reporting the issue.
>
> Patch attached. Comments are welcome.
>
>
> --
> Thanks,
> Tender Wang
>

In response to

Browse pgsql-hackers by date

  From Date Subject
Previous Message Nitin Motiani 2026-08-15 06:28:48 Re: Adding pg_dump flag for parallel export to pipes