BUG #19670: Silent Integer Overflow in time_pl_interval() Returns Wrong Time Value

From: PG Bug reporting form <noreply(at)postgresql(dot)org>
To: pgsql-bugs(at)lists(dot)postgresql(dot)org
Cc: 1950233439(at)qq(dot)com
Subject: BUG #19670: Silent Integer Overflow in time_pl_interval() Returns Wrong Time Value
Date: 2026-09-07 14:06:53
Message-ID: 19670-c4e56832fa6686f8@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: 19670
Logged by: Tianyu Shi
Email address: 1950233439(at)qq(dot)com
PostgreSQL version: 19beta3
Operating system: Ubuntu22.04
Description:

### Summary

`time_pl_interval()` in `src/backend/utils/adt/date.c` (lines 2174–2195)
silently produces incorrect results when adding a near-maximal interval to a
time value. The infinity guard (`INTERVAL_NOT_FINITE`) requires all three
interval fields to simultaneously hold their extreme values, so an interval
such as `'9223372036854 seconds'` (where `span->time = 9223372036854000000`,
slightly below `INT64_MAX`) bypasses the check entirely. The subsequent
unchecked addition `result = time + span->time` overflows signed 64-bit
integer arithmetic (C undefined behavior), returning a garbage `TimeADT`
with no error raised. Applications relying on correct time arithmetic for
security decisions — session expiry, scheduling windows, access-time
enforcement — may silently receive a corrupted value and act on it.

### PoC

Any authenticated database user can trigger the overflow with a single SQL
statement; no special privileges are required.

```sql
SELECT '23:59:59.999999'::time + interval '9223372036854 seconds';
```

To run against the local build:

```sql
-- Connect: ./build/bin/psql -h ./build/run -p 5432 postgres
SELECT
'23:59:59.999999'::time + interval '9223372036854 seconds' AS
actual_result,
make_time(0, 0, 0) + 24053999999::bigint * interval '1 microsecond' AS
expected_result,
CASE
WHEN ('23:59:59.999999'::time + interval '9223372036854 seconds') !=
(make_time(0, 0, 0) + 24053999999::bigint * interval '1
microsecond')
THEN 'MISMATCH: Integer overflow confirmed - result is WRONG'
ELSE 'MATCH: No overflow detected'
END AS verdict;
```

### Result

Expected output (correct modular arithmetic): `06:40:53.999999`.
Actual output observed: `19:59:04.448383` — an overflow-corrupted value
returned without any error or warning.

```
actual_result | expected_result | verdict
-----------------+-----------------+--------------------------------------------------------
19:59:04.448383 | 06:40:53.999999 | MISMATCH: Integer overflow confirmed -
result is WRONG
```

The semantic invariant `(time + interval) mod USECS_PER_DAY` is violated. No
exception is raised, so callers cannot distinguish a correct result from a
corrupted one.

Browse pgsql-bugs by date

  From Date Subject
Next Message PG Bug reporting form 2026-09-07 14:09:09 BUG #19671: IPv4 CIDR Prefix Integer Overflow Bypasses Validation in inet/cidr Casts
Previous Message PG Bug reporting form 2026-09-07 11:51:29 BUG #19664: nbtree: Assertion failure when a custom index AM reuses bthandler