Skip to content

Commit 5d9ef6b

Browse files
projectgusdpgeorge
authored andcommitted
py/objint_longlong: Fix left shift of negative values.
Previous comment was wrong, left shifting a negative value is UB in C. Use the same approach as small int shifts (from runtime.c). Signed-off-by: Angus Gratton <[email protected]>
1 parent 3185bb5 commit 5d9ef6b

File tree

1 file changed

+5
-5
lines changed

1 file changed

+5
-5
lines changed

py/objint_longlong.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,14 +208,14 @@ mp_obj_t mp_obj_int_binary_op(mp_binary_op_t op, mp_obj_t lhs_in, mp_obj_t rhs_i
208208

209209
case MP_BINARY_OP_LSHIFT:
210210
case MP_BINARY_OP_INPLACE_LSHIFT:
211-
if ((int)rhs_val < 0) {
211+
if (rhs_val < 0) {
212212
// negative shift not allowed
213213
mp_raise_ValueError(MP_ERROR_TEXT("negative shift count"));
214214
}
215-
result = lhs_val << (int)rhs_val;
216-
// Left-shifting of negative values is implementation defined in C, but assume compiler
217-
// will give us typical 2s complement behaviour unless the value overflows
218-
overflow = rhs_val > 0 && ((lhs_val >= 0 && result < lhs_val) || (lhs_val < 0 && result > lhs_val));
215+
overflow = rhs_val >= (sizeof(long long) * MP_BITS_PER_BYTE)
216+
|| lhs_val > (LLONG_MAX >> rhs_val)
217+
|| lhs_val < (LLONG_MIN >> rhs_val);
218+
result = (unsigned long long)lhs_val << rhs_val;
219219
break;
220220
case MP_BINARY_OP_RSHIFT:
221221
case MP_BINARY_OP_INPLACE_RSHIFT:

0 commit comments

Comments
 (0)