bug-m4
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

1.4.9: wrong results in signed division


From: Cesar Strauss
Subject: 1.4.9: wrong results in signed division
Date: Sat, 21 Apr 2007 20:30:56 -0300

Hi,

The eval macro in m4-1.4.9 gives wrong results in signed division:

$ ./m4
eval(-100/10)
429496719
(expected: -10)

m4-1.4.8 and HEAD of cvs are fine.

This is due to incorrectly casting of the operands to unsigned:

In src/eval.c (mult_term) line 724:
*v1 = (int32_t) ((uint32_t) *v1 / (uint32_t) v2);

(uint32_t) -100 = 4294967196
(uint32_t)   10 = 10
4294967196 / 10 = 429496719

This comment near the code seems relevant:

     /* Minimize undefined C behavior on overflow.  This code assumes
         that the implementation-defined overflow when casting
         unsigned to signed is a silent twos-complement
         wrap-around.  */

429496719 is smaller than 2^31, so there is no wrap-around.

I don't think any overflow handling is needed here, because the
quotient is always smaller than the dividend, in signed integer
division.

The following trivial patch for branch-1_4 solves the problem, by
reverting the change which introduced the regression.

2007-04-21  Cesar Strauss  <address@hidden> (tiny change)

        * src/eval.c (mult_term): Avoids casting the operands to unsigned
         in division. Fixes regression introduced in 2007-01-06.

Regards,
Cesar

Index: src/eval.c
=============================
RCS file: /sources/m4/m4/src/Attic/eval.c,v
retrieving revision 1.1.1.1.2.9
diff -u -3 -p -r1.1.1.1.2.9 eval.c
--- src/eval.c  9 Jan 2007 16:12:43 -0000       1.1.1.1.2.9
+++ src/eval.c  21 Apr 2007 18:56:27 -0000
@@ -721,7 +721,9 @@ mult_term (eval_token et, int32_t *v1)
            /* Avoid the x86 SIGFPE on INT_MIN / -1.  */
            *v1 = (int32_t) -(uint32_t) *v1;
          else
-           *v1 = (int32_t) ((uint32_t) *v1 / (uint32_t) v2);
+            /* Casting to unsigned would give wrong results here.
+               There is no danger of overflow in this case, anyway. */
+           *v1 = *v1 / v2;
          break;

        case MODULO:




reply via email to

[Prev in Thread] Current Thread [Next in Thread]