BUG #19584: tid input acceptance is platform-dependent: '(,5)'::tid yields (0,5) on glibc, errors on macOS

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: malis(at)pgrust(dot)com
Subject: BUG #19584: tid input acceptance is platform-dependent: '(,5)'::tid yields (0,5) on glibc, errors on macOS
Date: 2026-07-29 01:45:38
Message-ID: 19584-e60c446ba6f57c9c@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: 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.

Responses

Browse pgsql-bugs by date

  From Date Subject
Next Message solai v 2026-07-29 05:30:41 Re: DELETE FOR PORTION OF bypasses view WITH CHECK OPTION for leftover rows
Previous Message PG Bug reporting form 2026-07-29 00:49:33 BUG #19583: macaddr input accepts octet fields longer than 8 hex digits