diff options
author | Damien George <damien.p.george@gmail.com> | 2016-05-08 21:38:43 +0100 |
---|---|---|
committer | Damien George <damien.p.george@gmail.com> | 2016-05-08 21:38:43 +0100 |
commit | dc3faea0405dea803828f5a2be314734b8c166b6 (patch) | |
tree | 933f1f551d07f7986cce5afa3767124216ba3f13 /py | |
parent | d59c2e5e45389d4d280ccec52f88bc469b15a469 (diff) | |
download | micropython-dc3faea0405dea803828f5a2be314734b8c166b6.tar.gz micropython-dc3faea0405dea803828f5a2be314734b8c166b6.zip |
py/mpz: Fix bug with overflowing C-shift in division routine.
When DIG_SIZE=32, a uint32_t is used to store limbs, and no normalisation
is needed because the MSB is already set, then there will be left and
right shifts (in C) by 32 of a 32-bit variable, leading to undefined
behaviour. This patch fixes this bug.
Diffstat (limited to 'py')
-rw-r--r-- | py/mpz.c | 8 |
1 files changed, 4 insertions, 4 deletions
@@ -491,7 +491,7 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig, for (mpz_dig_t *den = den_dig, carry = 0; den < den_dig + den_len; ++den) { mpz_dig_t d = *den; *den = ((d << norm_shift) | carry) & DIG_MASK; - carry = d >> (DIG_SIZE - norm_shift); + carry = (mpz_dbl_dig_t)d >> (DIG_SIZE - norm_shift); } // now need to shift numerator by same amount as denominator @@ -501,7 +501,7 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig, for (mpz_dig_t *num = num_dig, carry = 0; num < num_dig + *num_len; ++num) { mpz_dig_t n = *num; *num = ((n << norm_shift) | carry) & DIG_MASK; - carry = n >> (DIG_SIZE - norm_shift); + carry = (mpz_dbl_dig_t)n >> (DIG_SIZE - norm_shift); } // cache the leading digit of the denominator @@ -618,14 +618,14 @@ STATIC void mpn_div(mpz_dig_t *num_dig, mp_uint_t *num_len, mpz_dig_t *den_dig, for (mpz_dig_t *den = den_dig + den_len - 1, carry = 0; den >= den_dig; --den) { mpz_dig_t d = *den; *den = ((d >> norm_shift) | carry) & DIG_MASK; - carry = d << (DIG_SIZE - norm_shift); + carry = (mpz_dbl_dig_t)d << (DIG_SIZE - norm_shift); } // unnormalise numerator (remainder now) for (mpz_dig_t *num = orig_num_dig + *num_len - 1, carry = 0; num >= orig_num_dig; --num) { mpz_dig_t n = *num; *num = ((n >> norm_shift) | carry) & DIG_MASK; - carry = n << (DIG_SIZE - norm_shift); + carry = (mpz_dbl_dig_t)n << (DIG_SIZE - norm_shift); } // strip trailing zeros |