| From: | "Tristan Partin" <tristan(at)partin(dot)io> |
|---|---|
| To: | <malis(at)pgrust(dot)com> |
| Cc: | <pgsql-bugs(at)lists(dot)postgresql(dot)org> |
| Subject: | Re: BUG #19584: tid input acceptance is platform-dependent: '(,5)'::tid yields (0,5) on glibc, errors on macOS |
| Date: | 2026-07-30 08:58:38 |
| Message-ID: | DKBS5Q4H0LL4.1BVC92UHVQT1A@partin.io |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-bugs |
On Wed Jul 29, 2026 at 7:24 AM CDT, PG Bug reporting form wrote:
> The following bug has been logged on the website:
>
> Bug reference: 19584
> Logged by: Michael Malis
> Email address: malis(at)pgrust(dot)com
> PostgreSQL version: 19beta2
> Operating system: Debian 13/aarch64 (glibc) and macOS 15/aarch64
> Description:
>
> The tid type accepts or rejects the same input string depending on
> the platform's C library, and on glibc platforms it converts empty
> coordinate fields to 0 rather than rejecting them.
>
> On Debian (official postgres:18 Docker image):
>
> SELECT version();
> version
> --------------------------------------------------------------------------------------------------------------------------
> PostgreSQL 18.4 (Debian 18.4-1.pgdg13+1) on aarch64-unknown-linux-gnu,
> compiled by gcc (Debian 14.2.0-19) 14.2.0, 64-bit
> (1 row)
>
> SELECT '(,5)'::tid;
> tid
> -------
> (0,5)
> (1 row)
>
> (likewise '(5,)' → (5,0) and '(,)' → (0,0))
>
> On macOS (Homebrew build):
>
> SELECT version();
> version
> -----------------------------------------------------------------------------------------------------------------------------
> PostgreSQL 18.4 (Homebrew) on aarch64-apple-darwin24.6.0, compiled by Apple
> clang version 17.0.0 (clang-1700.6.4.2), 64-bit
> (1 row)
>
> SELECT '(,5)'::tid;
> ERROR: invalid input syntax for type tid: "(,5)"
> LINE 1: SELECT '(,5)'::tid;
> ^
>
> Expected behavior: the same literal is either valid or invalid on
> every platform. I would expect rejection everywhere, since an empty
> block or offset field matches no documented form of the type, but
> either consistent behavior would resolve this report.
>
> Cause, from the source: tidin (src/backend/utils/adt/tid.c) parses
> each coordinate with
>
> errno = 0;
> cvt = strtoul(coord[0], &badp, 10);
> if (errno || *badp != DELIM)
> ereturn(...);
>
> When the field is empty, strtoul performs no conversion: it returns 0
> and sets *endptr to the start of the field, so badp points at the
> delimiter and the second test passes. Rejection then depends entirely
> on errno — and setting EINVAL for "no conversion could be performed"
> is optional per POSIX ("may fail"). glibc does not set it; macOS
> libc does. tidin never tests whether any digits were consumed
> (badp == coord[0]). Notably, uint32in_subr() in numutils.c — which
> tidin's own comment cites as "similar code" — does carry exactly that
> check ("|| endptr == s"), so the deterministic form already exists
> in the tree.
>
> This same platform difference was reported and diagnosed in April
> 2004 ("invalid input syntax for type tid: '(,)'", e.g.
> 200404061432(dot)i36EWab06319(at)candle(dot)pha(dot)pa(dot)us), where Tom Lane noted
> "the reason for the platform dependency is probably that strtoul()
> is setting errno on some machines and not others" and that "the TID
> input parser ... should never allow this". The trigger in that
> thread (an ODBC driver emitting '(,)') was fixed on the driver side;
> the parser was not changed.
>
> Happy to provide additional cases or a patch.
Thanks for the awesome report, again! I sent a patch[0] to fix this
issue to -hackers. I also spotted some other issues in the codebase, and
sent them in the series as well.
[0]: https://www.postgresql.org/message-id/DKBS2Z9CGARC.2T07O6TJYSE8B%40partin.io
--
Tristan Partin
PostgreSQL Contributors Team
AWS (https://aws.amazon.com)
| From | Date | Subject | |
|---|---|---|---|
| Previous Message | Tristan Partin | 2026-07-30 06:53:28 | Re: BUG #19587: hashchar (internal "char" type) depends on platform char signedness |