cio

a simple irc client
Download | Log | Files | Refs | README | LICENSE

commit 33ecac8de2f7d4eadf4dd9c426eb81577205112b
parent 96a55b50a593097455e1fad440b1cb7062750603
Author: Andrew Kloet <andrew@kloet.net>
Date:   Wed, 29 Apr 2026 00:27:17 -0400

fix UTC timestamp clobbering in pushf

The use of localtime() and gmtime() relies on a shared static buffer
internal to libc. When pushf() is called recursively during a day
change the inner call's gmtime() or localtime() would overwrite the
static memory used by the outer call, causing the local time to be
incorrectly rendered as UTC in the logs.

Switched to reentrant versions localtime_r() and gmtime_r() with
stack-allocated structs so each function call has isolated time data.

Diffstat:
Mcio.c | 20++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/cio.c b/cio.c @@ -455,7 +455,7 @@ pushf(int cn, const char *fmt, ...) va_list vl; time_t t; char *s; - const struct tm *tm, *gmtm; + struct tm tm, gmtm; if (blen + LineLen >= c->sz) { c->sz *= 2; @@ -465,17 +465,17 @@ pushf(int cn, const char *fmt, ...) c->eol = c->buf + blen; } t = time(0); - if (!(tm = localtime(&t))) + if (!localtime_r(&t, &tm)) die("cio: localtime failed"); if (c->last_mday == -1) { - c->last_mday = tm->tm_mday; - } else if (c->last_mday != tm->tm_mday) { - c->last_mday = tm->tm_mday; + c->last_mday = tm.tm_mday; + } else if (c->last_mday != tm.tm_mday) { + c->last_mday = tm.tm_mday; pushf(cn, "--- Day changed to %04d-%02d-%02d Anno Domini ---", - tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday); + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); } - n = strftime(c->eol, LineLen, DATEFMT, tm); - if (!(gmtm = gmtime(&t))) + n = strftime(c->eol, LineLen, DATEFMT, &tm); + if (!gmtime_r(&t, &gmtm)) die("cio: gmtime failed"); c->eol[n++] = ' '; va_start(vl, fmt); @@ -485,8 +485,8 @@ pushf(int cn, const char *fmt, ...) if (logfp) { fprintf(logfp, "%-12.12s\t%04d-%02d-%02dT%02d:%02d:%02dZ\t%s\n", c->name, - gmtm->tm_year + 1900, gmtm->tm_mon + 1, gmtm->tm_mday, - gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec, s); + gmtm.tm_year + 1900, gmtm.tm_mon + 1, gmtm.tm_mday, + gmtm.tm_hour, gmtm.tm_min, gmtm.tm_sec, s); fflush(logfp); } strlcat(c->buf, "\n", c->sz);