瀏覽代碼

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.
Rich Felker 11 年之前
父節點
當前提交
05453b37fc
共有 1 個文件被更改,包括 10 次插入7 次删除
  1. 10 7
      src/time/clock.c

+ 10 - 7
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;
 }