On 11/8/22 05:07, Robert Elz via tz wrote:
It seems likely that the simple fix is to replace the struct assignment with 7 individual assignment statements
tm.tm_year = t->tm_year; tm.tm_mon = t->tm_mon; /* ... */
Thanks for reporting the problem and suggesting a fix. Strictly speaking, the tzcode implementation of strftime doesn't violate the C standard here, since it implements the %s format, and the C standard doesn't specify the behavior of %s (which therefore can be undefined if you pass unset tm_yday etc.). However, the next release of POSIX will require support for %s, and as I recall the current draft for the next POSIX has messed up its spec for %s, so tzcode is on shaky ground here (as is the draft POSIX spec :-), and we can do better. Worse, there's a similar problem in localtime.c's implementation of mktime, for which the C standard clearly says mktime should not crash merely because tm_yday etc. is uninitialized. Here, tzcode mktime.c clearly is running afoul of the C standard. There's a subtle point here. By default tzcode's implementation of mktime sometimes looks at tm_gmtoff which the C standard says can be uninitialized and therefore has undefined behavior. On typical platforms, reading uninitialized data gives you arbitrary bits without trapping; on these platforms looking at tm_gmtoff will merely yield randomish bits (which tzcode mktime deals with reliably). However, on oddball platforms where reading uninitialized data traps or worse, you're supposed to compile code with -DUNINIT_TRAP so that mktime does not look at tm_gmtoff (and therefore has worse behavior in other ways). As you write, these are not likely to be problems on practical hosts. After all, the code has done it this way since 1989 with no bugs reported. However, we might as well do it correctly. I installed the attached patch which I hope addresses these issues satisfactorily.