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
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.