diff options
author | Rich Felker <dalias@aerifal.cx> | 2013-05-23 14:31:02 -0400 |
---|---|---|
committer | Rich Felker <dalias@aerifal.cx> | 2013-05-23 14:31:02 -0400 |
commit | 05453b37fc0343e53bc7f332047e901b3e1abb84 (patch) | |
tree | 46aec81077cc8062cb3a63e7a6504d9498bb1d25 | |
parent | 1e5eb73545ca6cfe8b918798835aaf6e07af5beb (diff) | |
download | musl-05453b37fc0343e53bc7f332047e901b3e1abb84.tar.gz musl-05453b37fc0343e53bc7f332047e901b3e1abb84.tar.bz2 musl-05453b37fc0343e53bc7f332047e901b3e1abb84.tar.xz musl-05453b37fc0343e53bc7f332047e901b3e1abb84.zip |
fix overflow behavior of clock() function
per Austin Group interpretation for issue #686, which cites the
requirements of ISO C, clock() cannot wrap. if the result is not
representable, it must return (clock_t)-1. in addition, the old code
was performing wrapping via signed overflow and thus invoking
undefined behavior.
since it seems impossible to accurately check for overflow with the
old times()-based fallback code, I have simply dropped the fallback
code for now, thus always returning -1 on ancient systems. if there's
a demand for making it work and somebody comes up with a way, it could
be reinstated, but the clock() function is essentially useless on
32-bit system anyway (it overflows in less than an hour).
it should be noted that I used LONG_MAX rather than ULONG_MAX, despite
32-bit archs using an unsigned type for clock_t. this discrepency with
the glibc/LSB type definitions will be fixed now; since wrapping of
clock_t is no longer supported, there's no use in it being unsigned.
-rw-r--r-- | src/time/clock.c | 17 |
1 files changed, 10 insertions, 7 deletions
diff --git a/src/time/clock.c b/src/time/clock.c index 78403af3..c348e398 100644 --- a/src/time/clock.c +++ b/src/time/clock.c @@ -1,15 +1,18 @@ #include <time.h> -#include <sys/times.h> -#include "syscall.h" +#include <limits.h> int __clock_gettime(clockid_t, struct timespec *); clock_t clock() { struct timespec ts; - struct tms tms; - if (!__clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts)) - return ts.tv_sec*1000000 + ts.tv_nsec/1000; - __syscall(SYS_times, &tms); - return (tms.tms_utime + tms.tms_stime)*10000; + + if (__clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts)) + return -1; + + if (ts.tv_sec > LONG_MAX/1000000 + || ts.tv_nsec/1000 > LONG_MAX-1000000*ts.tv_sec) + return -1; + + return ts.tv_sec*1000000 + ts.tv_nsec/1000; } |