| 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 #19590: to_date/to_timestamp "Y,YYY" accepts out-of-range values |
| Date: | 2026-07-31 05:57:01 |
| Message-ID: | 19590-991c467c2a601be0@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: 19590
Logged by: Michael Malis
Email address: malis(at)pgrust(dot)com
PostgreSQL version: 18.4
Operating system: Debian 18.4-1.pgdg13+1, aarch64
Description:
The Y,YYY template field parses its millennia component with a bare
sscanf(..., "%d", ...), which silently truncates values too large for int
instead of rejecting them, so out-of-range input yields a wrong year:
SELECT to_date('4294969320,024','Y,YYY'); -- 2024024-01-01 (expected:
error)
SELECT to_date('-4294965272,024','Y,YYY'); -- 2024024-01-01 (expected:
error)
4294969320 is 2^32 + 2024, so it truncates to 2024 and is read as 2024
millennia; any multiple of 2^32 works, and %d accepts a sign, so wrapped
negatives too. to_timestamp() shares the code path. Every other numeric
field rejects this:
SELECT to_date('4294969320','YYYY');
-- ERROR: value for "YYYY" in source string is out of range
Cause: DCH_Y_YYY is the only numeric field using raw sscanf; the others go
through from_char_parse_int_len(), which range-checks with strtol/ERANGE.
The existing pg_mul_s32_overflow guard in DCH_Y_YYY runs too late. %d has
already discarded the magnitude.
Suggested fix: after the sscanf, re-scan the millennia field with strtol and
reject ERANGE or out-of-int-range values, matching
from_char_parse_int_len():
errno = 0;
lval = strtol(s, &endptr, 10);
if (errno == ERANGE || lval < INT_MIN || lval > INT_MAX)
ereturn(escontext,,
(errcode(ERRCODE_DATETIME_FIELD_OVERFLOW),
errmsg("value for \"%s\" in source string is out of range",
"Y,YYY"),
errdetail("Value must be in the range %d to %d.", INT_MIN,
INT_MAX)));
strtol skips leading whitespace and stops at the comma exactly as %d does,
so this only adds a rejection path; the ERANGE test covers 32-bit-long
platforms where strtol saturates.
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Yugo Nagata | 2026-07-31 07:44:48 | Re: Two issues with REFRESH MATERIALIZED VIEW CONCURRENTLY |
| Previous Message | Tristan Partin | 2026-07-31 05:41:01 | Re: BUG #19589: JSON_QUERY rejects domain-over-bytea input when using FORMAT JSON ENCODING UTF8. |