diff options
Diffstat (limited to 'py/runtime_utils.c')
| -rw-r--r-- | py/runtime_utils.c | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/py/runtime_utils.c b/py/runtime_utils.c index b92c6bd76..50526b210 100644 --- a/py/runtime_utils.c +++ b/py/runtime_utils.c @@ -50,3 +50,63 @@ mp_obj_t mp_call_function_2_protected(mp_obj_t fun, mp_obj_t arg1, mp_obj_t arg2 return MP_OBJ_NULL; } } + +#if !MICROPY_USE_GCC_MUL_OVERFLOW_INTRINSIC +bool mp_mul_ll_overflow(long long int x, long long int y, long long int *res) { + bool overflow; + + // Check for multiply overflow; see CERT INT32-C + if (x > 0) { // x is positive + if (y > 0) { // x and y are positive + overflow = (x > (LLONG_MAX / y)); + } else { // x positive, y nonpositive + overflow = (y < (LLONG_MIN / x)); + } // x positive, y nonpositive + } else { // x is nonpositive + if (y > 0) { // x is nonpositive, y is positive + overflow = (x < (LLONG_MIN / y)); + } else { // x and y are nonpositive + overflow = (x != 0 && y < (LLONG_MAX / x)); + } // End if x and y are nonpositive + } // End if x is nonpositive + + if (!overflow) { + *res = x * y; + } + + return overflow; +} + +#define MP_UINT_MAX (~(mp_uint_t)0) +#define MP_INT_MAX ((mp_int_t)(MP_UINT_MAX >> 1)) +#define MP_INT_MIN (-MP_INT_MAX - 1) + +bool mp_mul_mp_int_t_overflow(mp_int_t x, mp_int_t y, mp_int_t *res) { + // Check for multiply overflow; see CERT INT32-C + if (x > 0) { // x is positive + if (y > 0) { // x and y are positive + if (x > (MP_INT_MAX / y)) { + return true; + } + } else { // x positive, y nonpositive + if (y < (MP_INT_MIN / x)) { + return true; + } + } // x positive, y nonpositive + } else { // x is nonpositive + if (y > 0) { // x is nonpositive, y is positive + if (x < (MP_INT_MIN / y)) { + return true; + } + } else { // x and y are nonpositive + if (x != 0 && y < (MP_INT_MAX / x)) { + return true; + } + } // End if x and y are nonpositive + } // End if x is nonpositive + + // Result doesn't overflow + *res = x * y; + return false; +} +#endif |
