From 6c713aecc983dd87631ad26e741ce0fcfde45031 Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Tue, 8 Nov 2022 15:45:51 -0800 Subject: [PROPOSED] Port mktime and strftime to strict C Problem reported by Robert Elz in: https://mm.icann.org/pipermail/tz/2022-November/032236.html * NEWS: Mention this. * localtime.c (time2sub): * strftime.c (_fmt): When preparing to call mktime, copy only the struct tm components that mktime needs. This avoids accessing components that may be uninitialized. --- NEWS | 4 ++++ localtime.c | 13 ++++++++++++- strftime.c | 11 ++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index d5ac440..4a05307 100644 --- a/NEWS +++ b/NEWS @@ -34,6 +34,10 @@ Unreleased, experimental changes Work around MS-Windows nmake incompatibility with POSIX. (Problem reported by Manuela Friedrich.) + Port mktime and strftime to debugging platforms where accessing + uninitialized data has undefined behavior (strftime problem + reported by Robert Elz). + Changes to build procedure New Makefile rule check_mild that skips checking whether Link diff --git a/localtime.c b/localtime.c index c556531..712be13 100644 --- a/localtime.c +++ b/localtime.c @@ -1972,7 +1972,18 @@ time2sub(struct tm *const tmp, struct tm yourtm, mytm; *okayp = false; - yourtm = *tmp; + + yourtm.tm_sec = tmp->tm_sec; + yourtm.tm_min = tmp->tm_min; + yourtm.tm_hour = tmp->tm_hour; + yourtm.tm_mday = tmp->tm_mday; + yourtm.tm_mon = tmp->tm_mon; + yourtm.tm_year = tmp->tm_year; + yourtm.tm_isdst = tmp->tm_isdst; +#if defined TM_GMTOFF && ! UNINIT_TRAP + yourtm.TM_GMTOFF = tmp->TM_GMTOFF; +#endif + if (do_norm_secs) { if (normalize_overflow(&yourtm.tm_min, &yourtm.tm_sec, SECSPERMIN)) diff --git a/strftime.c b/strftime.c index deba2b5..e312425 100644 --- a/strftime.c +++ b/strftime.c @@ -319,7 +319,16 @@ label: time_t) + 1]; time_t mkt; - tm = *t; + tm.tm_sec = t->tm_sec; + tm.tm_min = t->tm_min; + tm.tm_hour = t->tm_hour; + tm.tm_mday = t->tm_mday; + tm.tm_mon = t->tm_mon; + tm.tm_year = t->tm_year; + tm.tm_isdst = t->tm_isdst; +#if defined TM_GMTOFF && ! UNINIT_TRAP + tm.TM_GMTOFF = t->TM_GMTOFF; +#endif mkt = mktime(&tm); /* There is no portable, definitive test for whether whether mktime -- 2.38.1