Sat 08 Jan 2005 07:12:53 PM UTC, original submission:
Hello,
The Hurd version of uptime(1) (of w(1), actually) doesn't
work with uptimes larger than 2485 days, 12 hours, 19
minutes, 24 secondes (that is, larger than 214748364 which
is 2^31/10). For example, it prints 6.-128 years for
214748365 seconds, as you can see using the attached file
(which works on GNU/Linux as well).
This is due to an integer overflow in
libshouldbeinlibc/timefmt.c:fmt_named_len() at line
130. The first check (num < 10) is not enough to see if we
have a "low number". 214748365 secondes gives a num of 7,
which is less than 10, but will overflow when multiplied
by 10.
The overflow can be avoided by changing the condition.
tv->tv_sec < LONG_MAX sounds reasonable enough, as tv_sec
is a long in most OSes (at least, GNU/Linux, GNU/Hurd,
*BSD and Solaris). But POSIX defines the `tv_sec' field
in `struct timeval' to be a time_t, which can be any
integer or real type. Someone suggested to do something
like :
if (tv->tv_sec < (time_t) pow (2, CHAR_BIT * sizeof (time_t) - 1)
&& ...)
... but that is well, a bit too much (and adds a libm
dependency for libshouldbeinlibc).
Both solutions have been successfully tested on three
different systems. Note that uptime(1) prints a large
approximation of uptimes in those cases, albeit seemingly
correct.
|