Control: retitle -1 strftime(%Y) overflows into the negatives for very positive years Control: found -1 2.33-7 Under TZ=UTC0, the most positive and most negative times glibc accepts (i.e. "doesn't NULL, EOVERFLOW for") are 67768036191676799 (0x00F0C2AB7C54A97F) -67768040609740800 (0xFF0F3D537C550800) which are, respectively 2147485547-12-31 23:59:59 -2147481748-01-01 00:00:00 however, glibc strftime() apparently forgets to widen the intermediate representation, because strftime("%F %T") yields, respectively: -2147481749-12-31 23:59:59 -2147481748-01-01 00:00:00 these are 1 second apart, not ~2^32 years. As expected, 2147481748+1900 is 0x8000`0000, and 2147485547-1900 is 0x7FFF`FFFF. Measured via -- >8 -- #include <cstdio> #include <clocale> #include <cstdlib> #include <ctime> int main(int, const char ** argv) { std::setlocale(LC_ALL, ""); auto fmt = argv[1] ?: "no format!"; struct timespec ts {}; if(argv[1] && argv[2]) ts.tv_sec = strtoll(argv[2], nullptr, 0); else clock_gettime(CLOCK_REALTIME, &ts); char buf[4096]; std::strftime(buf, sizeof(buf), fmt, localtime(&ts.tv_sec)); std::puts(buf); } -- >8 -- Which produces (notably, coreutils date does /not/ have this issue): -- >8 -- $ TZ=UTC0 date +'%F %T' -d@67768036191676799 +2147485547-12-31 23:59:59 $ TZ=UTC0 date +'%F %T' -d@-67768040609740800 -2147481748-01-01 00:00:00 $ TZ=UTC0 ./strdate '%F %T' 67768036191676799 -2147481749-12-31 23:59:59 $ TZ=UTC0 ./strdate '%F %T' -67768040609740800 -2147481748-01-01 00:00:00 -- >8 -- I can reproduce this on bullseye and sid (2.33-7); substituting experimental (2.34) glibc unrelatedly segfaults. Best, наб
Attachment:
signature.asc
Description: PGP signature