INN commit: trunk/lib (timer.c)

INN Commit rra at isc.org
Fri Jun 26 17:59:29 UTC 2015


    Date: Friday, June 26, 2015 @ 10:59:29
  Author: iulius
Revision: 9909

lib/timer.c:  Make sure timer arithmetic is done in unsigned types

Some care is required.  The divison must be done in the signed type
(otherwise the answer is wrong if usec<0) but any operation that can
overflow (+ and *) must be done in an unsigned type.

In the current code the multiplication is done in the signed type.
If it overflows (as it will after a few weeks, on 32-bit platforms)
then we are already into undefined behaviour (C99 s6.5#5).

The subsequent conversion to an unsigned type does not make any
difference - the 'working type' for the multiplication is determined
by the operands alone, not by the treatment of the result.

Note that overflow behaviour for unsigned types (including conversion
of negative values to unsigned types) is defined:  the result is the
residue modulo 2^n (C99 s6.2.5#9).

Thanks to Richard Kettlewell for the patch.

Modified:
  trunk/lib/timer.c

---------+
 timer.c |    7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

Modified: timer.c
===================================================================
--- timer.c	2015-06-25 20:00:51 UTC (rev 9908)
+++ timer.c	2015-06-26 17:59:29 UTC (rev 9909)
@@ -114,6 +114,7 @@
 TMRgettime(bool reset)
 {
     unsigned long now;
+    long usec, msec;
     struct timeval tv;
 
     /* The time of the last summary, used as a base for times returned by
@@ -125,8 +126,10 @@
     static struct timeval base;
 
     gettimeofday(&tv, NULL);
-    now = (tv.tv_sec - base.tv_sec) * 1000;
-    now += (tv.tv_usec - base.tv_usec) / 1000;
+    now = (unsigned long)(tv.tv_sec - base.tv_sec) * 1000u;
+    usec = tv.tv_usec - base.tv_usec; /* maybe negative */
+    msec = usec / 1000;               /* still maybe negative */
+    now += (unsigned long)msec;
     if (reset)
         base = tv;
     return now;



More information about the inn-committers mailing list