In <https://github.com/eggert/tz/pull/37> (2026-01-10) the GitHub user Naveed8951 writes:

The TZif specification guarantees that tt_utoff is never INT32_MIN
so that 32-bit clients can safely negate it. However, tzloadbody()
previously accepted unvalidated values from untrusted TZif input.
A malformed or malicious file could therefore trigger signed integer
overflow during later offset arithmetic (e.g., negation for timezone /
altzone or offset-difference calculations), which is undefined behavior
in C.

Naveed8951 submitted a patch that would cause localtime.c to reject TZif files containing UT offsets outside the POSIX range -89999..93599 (-24:59:50 .. 25:59:59), the idea being that small offsets like that would not cause overflow.

Unfortunately, I think such a change would still allow undefined behavior in some cases, as overflow could still happen when adding a small offset to a large tm_sec or time_t value. Also, Internet RFC 9636 section 3.2 allows (though it discourages) UT offsets outside the POSIX range.

So instead, I fixed localtime.c to handle the outlandish offsets correctly. As a special case, localtime.c (and zic.c) now reject a UT offset exactly equal to -2**31, as RFC 9636 does not allow that and it can easily cause trouble in callers that negate a UT offset stored in a 32-bit integer.

Reply via email to