~ chicken-core (chicken-5) 9d8c2cbd321c716d867a6aadf7a45e94f4d691c3
commit 9d8c2cbd321c716d867a6aadf7a45e94f4d691c3
Author: Peter Bex <peter@more-magic.net>
AuthorDate: Sat Jun 20 20:55:23 2015 +0200
Commit: Christian Kellermann <ckeen@pestilenz.org>
CommitDate: Thu Jun 25 09:34:44 2015 +0200
Avoid shifting signed values, which is undefined behaviour in C.
Signed-off-by: Christian Kellermann <ckeen@pestilenz.org>
diff --git a/chicken.h b/chicken.h
index 8f8d82e0..66c276ab 100644
--- a/chicken.h
+++ b/chicken.h
@@ -864,7 +864,7 @@ DECL_C_PROC_p0 (128, 1,0,0,0,0,0,0,0)
/* This is word-size dependent: */
#ifdef C_SIXTY_FOUR
# define C_align(n) C_align8(n)
-# define C_wordstobytes(n) ((n) << 3)
+# define C_wordstobytes(n) ((C_uword)(n) << 3)
# define C_bytestowords(n) (((n) + 7) >> 3)
# define C_wordsperdouble(n) (n)
# define C_WORD_MIN LONG_MIN
@@ -872,9 +872,9 @@ DECL_C_PROC_p0 (128, 1,0,0,0,0,0,0,0)
# define C_UWORD_MAX ULONG_MAX
#else
# define C_align(n) C_align4(n)
-# define C_wordstobytes(n) ((n) << 2)
+# define C_wordstobytes(n) ((C_uword)(n) << 2)
# define C_bytestowords(n) (((n) + 3) >> 2)
-# define C_wordsperdouble(n) ((n) << 1)
+# define C_wordsperdouble(n) ((C_uword)(n) << 1)
# define C_WORD_MIN INT_MIN
# define C_WORD_MAX INT_MAX
# define C_UWORD_MAX UINT_MAX
@@ -1086,7 +1086,7 @@ DECL_C_PROC_p0 (128, 1,0,0,0,0,0,0,0)
#endif
#define C_stack_pointer_test ((C_word *)C_alloca(1))
#define C_demand_2(n) (((C_word *)C_fromspace_top + (n)) < (C_word *)C_fromspace_limit)
-#define C_fix(n) (((C_word)(n) << C_FIXNUM_SHIFT) | C_FIXNUM_BIT)
+#define C_fix(n) ((C_word)((C_uword)(n) << C_FIXNUM_SHIFT) | C_FIXNUM_BIT)
#define C_unfix(x) C_CHECKp(x,C_fixnump(C_VAL1(x)),((C_VAL1(x)) >> C_FIXNUM_SHIFT))
#define C_make_character(c) (((((C_uword)(c)) & C_CHAR_BIT_MASK) << C_CHAR_SHIFT) | C_CHARACTER_BITS)
#define C_character_code(x) C_CHECKp(x,C_charp(C_VAL1(x)),((C_word)(C_VAL1(x)) >> C_CHAR_SHIFT) & C_CHAR_BIT_MASK)
@@ -1102,7 +1102,7 @@ DECL_C_PROC_p0 (128, 1,0,0,0,0,0,0,0)
#define C_mk_nbool(x) ((x) ? C_SCHEME_FALSE : C_SCHEME_TRUE)
#define C_port_file(p) C_CHECKp(p,C_portp(C_VAL1(p)),(C_FILEPTR)C_block_item(C_VAL1(p), 0))
#define C_data_pointer(b) C_CHECKp(b,C_blockp((C_word)C_VAL1(b)),(void *)(((C_SCHEME_BLOCK *)(C_VAL1(b)))->data))
-#define C_fitsinfixnump(n) (((n) & C_INT_SIGN_BIT) == (((n) & C_INT_TOP_BIT) << 1))
+#define C_fitsinfixnump(n) (((n) & C_INT_SIGN_BIT) == ((C_uword)((n) & C_INT_TOP_BIT) << 1))
#define C_ufitsinfixnump(n) (((n) & (C_INT_SIGN_BIT | (C_INT_SIGN_BIT >> 1))) == 0)
#define C_quickflonumtruncate(n) (C_fix((C_word)C_flonum_magnitude(n)))
#define C_and(x, y) (C_truep(x) ? (y) : C_SCHEME_FALSE)
@@ -1220,7 +1220,7 @@ DECL_C_PROC_p0 (128, 1,0,0,0,0,0,0,0)
#define C_fixnum_or(n1, n2) (C_u_fixnum_or(n1, n2) | C_FIXNUM_BIT)
#define C_fixnum_xor(n1, n2) (((n1) ^ (n2)) | C_FIXNUM_BIT)
#define C_fixnum_not(n) ((~(n)) | C_FIXNUM_BIT)
-#define C_fixnum_shift_left(n1, n2) (C_fix(C_unfix(n1) << C_unfix(n2)))
+#define C_fixnum_shift_left(n1, n2) (C_fix(((C_uword)C_unfix(n1) << (C_uword)C_unfix(n2))))
#define C_fixnum_shift_right(n1, n2) (((n1) >> C_unfix(n2)) | C_FIXNUM_BIT)
#define C_u_fixnum_negate(n) (-(n) + 2 * C_FIXNUM_BIT)
#define C_fixnum_negate(n) (C_u_fixnum_negate(n) | C_FIXNUM_BIT)
diff --git a/runtime.c b/runtime.c
index 75ca6549..f592f935 100644
--- a/runtime.c
+++ b/runtime.c
@@ -218,7 +218,7 @@ extern void _C_do_apply_hack(void *proc, C_word *args, int count) C_noret;
#define is_fptr(x) (((x) & C_GC_FORWARDING_BIT) != 0)
#define ptr_to_fptr(x) ((((x) >> FORWARDING_BIT_SHIFT) & 1) | C_GC_FORWARDING_BIT | ((x) & ~1))
-#define fptr_to_ptr(x) (((x) << FORWARDING_BIT_SHIFT) | ((x) & ~(C_GC_FORWARDING_BIT | 1)))
+#define fptr_to_ptr(x) (((C_uword)(x) << FORWARDING_BIT_SHIFT) | ((x) & ~(C_GC_FORWARDING_BIT | 1)))
#define C_check_flonum(x, w) if(C_immediatep(x) || C_block_header(x) != C_FLONUM_TAG) \
barf(C_BAD_ARGUMENT_TYPE_NO_FLONUM_ERROR, w, x);
@@ -5316,7 +5316,7 @@ C_regparm C_word C_fcall C_a_i_arithmetic_shift(C_word **a, int c, C_word n1, C_
if(sgn < 0) {
if(s < 0) nn >>= -s;
- else nn <<= s;
+ else nn = (C_word)((C_uword)nn << s);
if(C_fitsinfixnump(nn)) return C_fix(nn);
else return C_flonum(a, nn);
@@ -7633,7 +7633,7 @@ C_regparm C_word C_fcall convert_string_to_number(C_char *str, int radix, C_word
return 0;
}
- else if((n & C_INT_SIGN_BIT) != ((n << 1) & C_INT_SIGN_BIT)) { /* doesn't fit into fixnum? */
+ else if((n & C_INT_SIGN_BIT) != (((C_uword)n << 1) & C_INT_SIGN_BIT)) { /* doesn't fit into fixnum? */
if(*eptr == '\0' || !C_strncmp(eptr, ".0", C_strlen(eptr))) {
*flo = (double)n;
return 2;
@@ -7943,7 +7943,7 @@ void C_ccall C_peek_signed_integer(C_word c, C_word closure, C_word k, C_word v,
C_word x = C_block_item(v, C_unfix(index));
C_alloc_flonum;
- if((x & C_INT_SIGN_BIT) != ((x << 1) & C_INT_SIGN_BIT)) {
+ if((x & C_INT_SIGN_BIT) != (((C_uword)x << 1) & C_INT_SIGN_BIT)) {
C_kontinue_flonum(k, (double)x);
}
@@ -7956,7 +7956,7 @@ void C_ccall C_peek_unsigned_integer(C_word c, C_word closure, C_word k, C_word
C_word x = C_block_item(v, C_unfix(index));
C_alloc_flonum;
- if((x & C_INT_SIGN_BIT) || ((x << 1) & C_INT_SIGN_BIT)) {
+ if((x & C_INT_SIGN_BIT) || (((C_uword)x << 1) & C_INT_SIGN_BIT)) {
C_kontinue_flonum(k, (double)(C_uword)x);
}
@@ -8845,10 +8845,10 @@ static C_regparm C_word C_fcall decode_literal2(C_word **ptr, C_char **str,
return (C_word)(*(*str - 1));
case C_FIXNUM_BIT:
- val = *((*str)++) << 24; /* always big endian */
- val |= (*((*str)++) & 0xff) << 16;
- val |= (*((*str)++) & 0xff) << 8;
- val |= (*((*str)++) & 0xff);
+ val = (C_uword)*((*str)++) << 24; /* always big endian */
+ val |= ((C_uword)*((*str)++) & 0xff) << 16;
+ val |= ((C_uword)*((*str)++) & 0xff) << 8;
+ val |= ((C_uword)*((*str)++) & 0xff);
return C_fix(val);
#ifdef C_SIXTY_FOUR
Trap