scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

commit 108a79e6a070b320c7efd64b51b215d3ff73cb7d
parent 1ead11308a65c7fd1b816a007a597b4569b8c7f3
Author: Roberto E. Vargas Caballero <k0ga@shike2.net>
Date:   Tue, 14 Apr 2026 17:56:38 +0200

libc/time: Force values for all the tzone vars

The tzone variables are used in different places, and they are
assumed to have correct values. This invariant was not enforced
by _tzset() and _tzname[0] and _tzname[1] could have a NULL pointer
that would produce a segmentation fault when the TZ variable
was not set in case of using any of the strftime() specifiers
that require these strings or in the function gmtoff() of
localtime.c.

Diffstat:
Msrc/libc/arch/posix/_systime.c | 5+++--
Msrc/libc/arch/posix/_tzone.c | 1+
Msrc/libc/libc.h | 40++++++++++++++++++++--------------------
Msrc/libc/time/localtime.c | 4+++-
4 files changed, 27 insertions(+), 23 deletions(-)

diff --git a/src/libc/arch/posix/_systime.c b/src/libc/arch/posix/_systime.c @@ -5,12 +5,13 @@ time_t _systime(struct tm *tm) { + int i; time_t t = 0; int year = tm->tm_year + MINYEAR; - for (int i = EPOCH; i < year; ++i) + for (i = EPOCH; i < year; ++i) t += _daysyear(i) * SECDAY; - for (int i = 0; i < tm->tm_mon; ++i) + for (i = 0; i < tm->tm_mon; ++i) t += _daysmon[i] * SECDAY; t += tm->tm_sec; diff --git a/src/libc/arch/posix/_tzone.c b/src/libc/arch/posix/_tzone.c @@ -230,6 +230,7 @@ _tzset(void) char *tz = getenv("TZ"); int i; + _tzname[1] = _tzname[0] = "UTC"; _tzstdoff = _tzdstoff = (time_t) -1; _tzstart = _tzend = (time_t) -1; _tzjulian = 0; diff --git a/src/libc/libc.h b/src/libc/libc.h @@ -1,3 +1,17 @@ +struct tm; +struct _FILE; + +void *_getheap(void); +int _dtoi(char c); + +#ifdef stdin +int _allocbuf(FILE *); +int _flsbuf(FILE *); +FILE *_fpopen(const char * restrict, const char *restrict, + FILE *restrict); +#endif + +#ifdef _TIME_H enum { SUN, MON, @@ -19,33 +33,19 @@ enum { #define SECHOUR (60 * SECMIN) /* 3600 */ #define SECDAY (24 * SECHOUR) /* 86400 */ -struct tm; -struct _FILE; - -void *_getheap(void); -int _dtoi(char c); - -#ifdef stdin -int _allocbuf(FILE *); -int _flsbuf(FILE *); -FILE *_fpopen(const char * restrict, const char *restrict, - FILE *restrict); -#endif - -#ifdef _TIME_H +/* _tzone.c variables */ extern time_t _tzstdoff, _tzdstoff; extern time_t _tzstart, _tzend; +extern char *_tzname[2]; +extern int _tzjulian; -time_t _systime(struct tm *); -#endif +extern int _daysmon[12]; +time_t _systime(struct tm *); void _tzset(void); int _daysyear(int); int _newyear(int); - -extern int _tzjulian; -extern int _daysmon[12]; -extern char *_tzname[2]; +#endif extern unsigned _exitn; extern void (*_flushall)(void); diff --git a/src/libc/time/localtime.c b/src/libc/time/localtime.c @@ -7,7 +7,6 @@ struct tzone { char *name; int gmtoff; - int isdst; }; #include "tz.c" @@ -17,6 +16,9 @@ gmtoff(char *tz) { struct tzone *t; + if (!strcmp(tz, "UTC")) + return 0; + for (t = tzones; t->name; t++) { if (!strcmp(t->name, tz)) return t->gmtoff;