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:
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;