Use (arith) 1 << ... when getting the sign bit.
authorGeorge Koehler <xkernigh@netscape.net>
Sun, 29 Oct 2017 21:45:10 +0000 (17:45 -0400)
committerGeorge Koehler <xkernigh@netscape.net>
Sun, 29 Oct 2017 21:45:10 +0000 (17:45 -0400)
This prevents an overflow reported by @hexcoder- in
https://github.com/davidgiven/ack/issues/56

lang/cem/cpp.ansi/LLlex.c used a plain 1 << ... and caused an overflow
on machines where sizeof(int) < sizeof(long).  Using 1L << ... would
work for now but might fail later if arith became long long.

C doesn't specify whether negative integers use 2's complement or some
other format.  Therefore, (arith) 1 << ... has an undefined value.  It
should still work because the value is some integer where the sign bit
is set and all other bits are clear.

(unsigned arith) 1 << ... would also get the sign bit, but casting it
from unsigned back to signed would make the same undefined value.

(arith) -1 << ... would assume 2's complement.

lang/cem/cpp.ansi/LLlex.c
lang/cem/cpp.ansi/arith.h
lang/cem/cpp.ansi/ch3bin.c
lang/m2/comp/cstoper.c
lang/m2/comp/type.c

index 7aa0a1e..5b25a49 100644 (file)
@@ -261,7 +261,7 @@ garbage:
                register int base = 10, vch;
                register arith val = 0;
                int ovfl = 0;
-               arith ubound = ~(1<<(sizeof(arith)*8-1))/(base/2);
+               arith ubound = max_arith/(base/2);
 
                /* Since the preprocessor only knows integers and has
                 * nothing to do with ellipsis we just return when the
index be74a18..37a5f63 100644 (file)
@@ -16,3 +16,7 @@
 /*     All preprocessor arithmetic should be done in longs.
 */
 #define        arith   long                            /* dummy */
+
+#define        arith_size      (sizeof(arith))
+#define        arith_sign      ((arith) 1 << (arith_size * 8 - 1))
+#define        max_arith       (~arith_sign)
index f9f43cf..c458487 100644 (file)
@@ -8,8 +8,6 @@
 #include       "Lpars.h"
 #include       "arith.h"
 
-#define arith_sign (1L << (sizeof(arith)*8-1))
-
 ch3bin(pval, pis_uns, oper, val, is_uns)
        register arith *pval, val;
        int oper, is_uns, *pis_uns;
index 9d7fea0..53dfd0e 100644 (file)
@@ -28,7 +28,7 @@
 
 extern char    *symbol2str();
 
-#define arith_sign     ((arith) (1L << (sizeof(arith) * 8 - 1)))
+#define arith_sign     ((arith) 1 << (sizeof(arith) * 8 - 1))
 
 #ifndef NOCROSS
 arith full_mask[MAXSIZE+1];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */
index bbf4841..5912771 100644 (file)
@@ -51,8 +51,6 @@ arith
        pointer_size = SZ_POINTER;
 #endif
 
-#define arith_sign     ((arith) (1L << (sizeof(arith) * 8 - 1)))
-
 arith  ret_area_size;
 
 t_type