Browse Source

py: Fix bug with right-shifting small ints by large amounts.

Undefined behavior in C, needs explicit check.
pull/954/merge
Paul Sokolovsky 10 years ago
parent
commit
039887a0ac
  1. 5
      py/compile.c
  2. 5
      py/runtime.c
  3. 14
      tests/basics/int_small.py

5
py/compile.c

@ -233,6 +233,11 @@ STATIC mp_parse_node_t fold_constants(compiler_t *comp, mp_parse_node_t pn, mp_m
} }
} else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) { } else if (MP_PARSE_NODE_IS_TOKEN_KIND(pns->nodes[1], MP_TOKEN_OP_DBL_MORE)) {
// int >> int // int >> int
if (arg1 >= BITS_PER_WORD) {
// Shifting to big amounts is underfined behavior
// in C and is CPU-dependent; propagate sign bit.
arg1 = BITS_PER_WORD - 1;
}
pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1); pn = mp_parse_node_new_leaf(MP_PARSE_NODE_SMALL_INT, arg0 >> arg1);
} else { } else {
// shouldn't happen // shouldn't happen

5
py/runtime.c

@ -337,6 +337,11 @@ mp_obj_t mp_binary_op(mp_uint_t op, mp_obj_t lhs, mp_obj_t rhs) {
nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count")); nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "negative shift count"));
} else { } else {
// standard precision is enough for right-shift // standard precision is enough for right-shift
if (rhs_val >= BITS_PER_WORD) {
// Shifting to big amounts is underfined behavior
// in C and is CPU-dependent; propagate sign bit.
rhs_val = BITS_PER_WORD - 1;
}
lhs_val >>= rhs_val; lhs_val >>= rhs_val;
} }
break; break;

14
tests/basics/int_small.py

@ -48,3 +48,17 @@ a -= 1
print(a) print(a)
# This would overflow # This would overflow
#a -= 1 #a -= 1
# Shifts to big amounts are undefined behavior in C and is CPU-specific
# These are compile-time constexprs
print(1 >> 32)
print(1 >> 64)
print(1 >> 128)
# These are runtime calcs
a = 1
print(a >> 32)
print(a >> 64)
print(a >> 128)

Loading…
Cancel
Save