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.
This commit is contained in:
8
py/mpz.c
8
py/mpz.c
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user