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`,
and 2147485547-1900 is 0x7FFF`.
Measured via
-- >8 --
#include
#include
#include
#include
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,
наб
signature.asc
Description: PGP signature