Repository navigation
Conversation
atoi() returns int, so every server-link timestamp parsed with it saturates at INT_MAX (2038-01-19 03:14:07 UTC), truncating before the value is ever widened into its time_t destination. This breaks even on a 64-bit time_t system: the loss happens inside atoi(). The fix is input-only and protocol-neutral. ircd_snprintf's %Tu already emits a full time_t, and timestamps travel as decimal ASCII, so a wide parse is forward-compatible with existing peers and needs no protocol change. Add a helper time_t atotime(const char*) that parses at full width via strtoll(), and convert every timestamp parse that feeds a time_t: - server link start/timestamp (m_server) - nick lastnick (m_nick, s_user) - channel creation TS (CREATE/JOIN/BURST/DESTRUCT) - MODE channel TS recv_ts (channel.c) - TOPIC times (m_topic), INVITE ts (m_invite), SETTIME (m_settime) - G-line expire/lastmod/lifetime (m_gline) - jupe expire_off/lastmod (m_jupe) - the RPING lag sample (m_rping; its local int is widened to time_t) Also fix a related 32-bit truncation: acc_id and acc_flags are uint64_t but were parsed with atoi(); use strtoull() so account ids above 2^31 survive. Non-time atoi() calls (ports, hop counts, protocol numbers, op-levels, counts, umode masks, CAP version, millisecond RTT deltas) are left unchanged. Add an atotime() regression test to ircd_string_t asserting that a post-2038 value (2200000000, 2039-09-13) round-trips intact on a 64-bit time_t build, guarded so a legitimately 32-bit time_t build skips rather than fails. Closes UndernetIRC#119.
The atotime() timestamp fix relies on a 64-bit time_t; on a 32-bit time_t the wire timestamps still overflow in 2038, one step later. Add a configure check that measures sizeof(time_t) and, if it is under 8 bytes, tries the glibc remedy (-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64) before giving up. If a 64-bit time_t still cannot be obtained it warns by default, or fails when --enable-y2038-strict is given (useful for CI and release builds). configure is generated (gitignored) and regenerated via autogen.sh, so only configure.ac changes. Relates to UndernetIRC#119.
MrIron-no
force-pushed
the
fix/y2038-atoi-timestamps
branch
from
September 15, 2026 11:25
19bf078 to
0648d58
Compare
Contributor
Author
|
Force-pushed an amend: the first pass missed three timestamp |
MrIron-no
added a commit
to MrIron-no/ircu2
that referenced
this pull request
Oct 6, 2026
atotime() arrives with the Year 2038 change (UndernetIRC#122), which this branch does not carry; use atoi() like the surrounding timestamp parsing until then.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #119.
Summary
Server-link timestamps were parsed with
atoi(), which returnsintandtherefore saturates at
INT_MAX(2038-01-19 03:14:07 UTC) — the truncationhappens inside
atoi(), before the value is widened into itstime_tdestination, so it breaks even on a 64-bit
time_tsystem.The fix is input-only and protocol-neutral:
ircd_snprintf's%Tualreadyemits a full
time_t, and timestamps travel as decimal ASCII, so a wide parseis forward-compatible with existing peers and needs no protocol change.
Changes
New helper.
time_t atotime(const char *)inircd_string.cparses at fullwidth via
strtoll().~22 timestamp parses converted from
atoi()toatotime():server link start/timestamp (
m_server), nicklastnick(m_nick,s_user), channel creation TS (CREATE/JOIN/BURST/DESTRUCT), theMODErecv_ts(channel.c),TOPICtimes,INVITE,SETTIME, G-lineexpire/lastmod/lifetime, jupelastmod, and the RPING lag sample (itslocal
intwidened totime_t).Related 32-bit truncation.
acc_idandacc_flagsareuint64_tbut wereparsed with
atoi(); usestrtoull()so account ids above 2^31 survive.Left unchanged: non-time
atoi()calls (ports, hop counts, protocolnumbers, op-levels, counts, umode masks, CAP version, millisecond RTT deltas).
Build guard (
configure.ac). The fix assumes a 64-bittime_t. Added acheck that measures
sizeof(time_t), tries the glibc remedy(
-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64) if it is smaller, and then warns bydefault or fails under
--enable-y2038-strict(for CI/release builds).configureis generated and regenerated viaautogen.sh, so onlyconfigure.acchanges here.Tests
Added an
atotime()regression test toircd_string_tasserting that apost-2038 value (
2200000000, 2039-09-13) round-trips intact on a 64-bittime_tbuild, guarded so a legitimately 32-bittime_tbuild skips ratherthan fails.
Validation
Built and run through the regular build (after
./autogen.sh):ircdbinary builds clean, no new warnings.ircd_string_tpasses; the post-2038 value is preserved (atoiwould turnit into
-2094967296).configurereports the 64-bit case silently; the warn and--enable-y2038-stricterror paths were both exercised and fire correctly.