Re: Integer wraparound bug with eval on OS X
Eric Blake <[email protected]>
| Newsgroups | gmane.comp.gnu.m4.patches,gmane.comp.gnu.m4.bugs |
|---|---|
| Message-ID | <[email protected]> |
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi Gary, According to Eric Blake on 5/1/2007 6:48 AM: > According to Gary V. Vaughan on 4/30/2007 10:49 AM: >> Hi Eric, > >> I think your recent patch to eval has either broken something, or else >> tickled a long standing bug. Using the latest gnulib and m4 HEAD, test >> 135 is failing. > > >> eval(-4 >> 65) >> -1 >> eval(-4 >> 64) >> -1 >> eval(-4 >> 63) >> -1 > > It looks like the failure is due to undefined C code (shifting by an > amount larger than the width of the type), and that the testsuite is just > tickling a long-standing bug. branch-1_4 is immune because it > intentionally masks the shift amount to bring it back into width, so I > will have to port some of that code to HEAD. Thanks for the heads-up on this. Fixed like so, and sorry for the delay: 2007-05-24 Eric Blake <[email protected]> Provide consistent shift semantics regardless of hardware. * modules/m4.c (numb_lshift, numb_rshift, numb_urshift): Mask before shifting. (number, unumber): Always use [u]intmax_t. Reported by Gary V. Vaughan. - -- Don't work too hard, make some time for fun as well! Eric Blake [email protected] -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (Cygwin) Comment: Public key at home.comcast.net/~ericblake/eblake.gpg Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org iD8DBQFGVZIN84KuGfSFAYARAvl2AJ9a3ggUZULcgrqr5mkn+Oo6b08B0ACfUyDl yD393QiGMHKeAmNUC6WilGM= =FdqY -----END PGP SIGNATURE----- _______________________________________________ M4-patches mailing list [email protected] http://lists.gnu.org/mailman/listinfo/m4-patches
m4.patch261
(text/plain, 1.9 KB)
Index: modules/m4.c
===================================================================
RCS file: /sources/m4/m4/modules/m4.c,v
retrieving revision 1.107
diff -u -p -r1.107 m4.c
--- modules/m4.c 24 May 2007 12:54:13 -0000 1.107
+++ modules/m4.c 24 May 2007 13:24:04 -0000
@@ -100,14 +100,8 @@ extern void m4_make_temp (m4 *contex
BUILTIN (undivert, false, false, false, 0, -1 ) \
-#if defined(SIZEOF_LONG_LONG_INT) && SIZEOF_LONG_LONG_INT > 0
-/* Use GNU long long int if available. */
-typedef long long int number;
-typedef unsigned long long int unumber;
-#else
-typedef long int number;
-typedef unsigned long int unumber;
-#endif
+typedef intmax_t number;
+typedef uintmax_t unumber;
static void include (m4 *context, int argc, m4_symbol_value **argv,
bool silent);
@@ -1106,10 +1100,21 @@ M4BUILTIN_HANDLER (translit)
does not support. */
#define numb_invert(x) return NEGATIVE_EXPONENT
-#define numb_lshift(c, x, y) (*(x) = (*(x) << *(y)))
-#define numb_rshift(c, x, y) (*(x) = (*(x) >> *(y)))
-#define numb_urshift(c, x, y) \
- (*(x) = (number) ((unumber) *(x) >> (unumber) *(y)))
+/* Minimize undefined C behavior (shifting by a negative number,
+ shifting by the width or greater, left shift overflow, or
+ right shift of a negative number). Implement Java 32-bit
+ wrap-around semantics. This code assumes that the
+ implementation-defined overflow when casting unsigned to
+ signed is a silent twos-complement wrap-around. */
+#define shift_mask (sizeof (number) * CHAR_BIT - 1)
+#define numb_lshift(c, x, y) \
+ (*(x) = (number) ((unumber) *(x) << (*(y) & shift_mask)))
+#define numb_rshift(c, x, y) \
+ (*(x) = (number) (*(x) < 0 \
+ ? ~(~(unumber) *(x) >> (*(y) & shift_mask)) \
+ : (unumber) *(x) >> (*(y) & shift_mask)))
+#define numb_urshift(c, x, y) \
+ (*(x) = (number) ((unumber) *(x) >> (*(y) & shift_mask)))
/* The function ntoa () converts VALUE to a signed ascii representation in