Use (arith) 1 << ... when getting the sign bit.

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.
This commit is contained in:
George Koehler 2017-10-29 17:45:10 -04:00
parent d36807b395
commit 59b3c10563
5 changed files with 6 additions and 6 deletions

View file

@ -261,7 +261,7 @@ garbage:
register int base = 10, vch; register int base = 10, vch;
register arith val = 0; register arith val = 0;
int ovfl = 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 /* Since the preprocessor only knows integers and has
* nothing to do with ellipsis we just return when the * nothing to do with ellipsis we just return when the

View file

@ -16,3 +16,7 @@
/* All preprocessor arithmetic should be done in longs. /* All preprocessor arithmetic should be done in longs.
*/ */
#define arith long /* dummy */ #define arith long /* dummy */
#define arith_size (sizeof(arith))
#define arith_sign ((arith) 1 << (arith_size * 8 - 1))
#define max_arith (~arith_sign)

View file

@ -8,8 +8,6 @@
#include "Lpars.h" #include "Lpars.h"
#include "arith.h" #include "arith.h"
#define arith_sign (1L << (sizeof(arith)*8-1))
ch3bin(pval, pis_uns, oper, val, is_uns) ch3bin(pval, pis_uns, oper, val, is_uns)
register arith *pval, val; register arith *pval, val;
int oper, is_uns, *pis_uns; int oper, is_uns, *pis_uns;

View file

@ -28,7 +28,7 @@
extern char *symbol2str(); extern char *symbol2str();
#define arith_sign ((arith) (1L << (sizeof(arith) * 8 - 1))) #define arith_sign ((arith) 1 << (sizeof(arith) * 8 - 1))
#ifndef NOCROSS #ifndef NOCROSS
arith full_mask[MAXSIZE+1];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */ arith full_mask[MAXSIZE+1];/* full_mask[1] == 0xFF, full_mask[2] == 0xFFFF, .. */

View file

@ -51,8 +51,6 @@ arith
pointer_size = SZ_POINTER; pointer_size = SZ_POINTER;
#endif #endif
#define arith_sign ((arith) (1L << (sizeof(arith) * 8 - 1)))
arith ret_area_size; arith ret_area_size;
t_type t_type