mirror of
https://git.tartarus.org/simon/putty.git
synced 2025-01-08 08:58:00 +00:00
Fix mp_{eq,hs}_integer(tiny, huge).
The comparison functions between an mp_int and an integer worked by
walking along the mp_int, comparing each of its words to the
corresponding word of the integer. When they ran out of mp_int, they'd
stop.
But this overlooks the possibility that they might not have run out of
_integer_ yet! If BIGNUM_INT_BITS is defined to be less than the size
of a uintmax_t, then comparing (say) the uintmax_t 0x8000000000000001
against a one-word mp_int containing 0x0001 would return equality,
because it would never get as far as spotting the high bit of the
integer.
Fixed by iterating up to the max of the number of BignumInts in the
mp_int and the number that cover a uintmax_t. That means we have to
use mp_word() instead of a direct array lookup to get the mp_int words
to compare against, since now the word indices might be out of range.
(cherry picked from commit 289d8873ec
)
This commit is contained in:
parent
b2e5b20ab7
commit
f86f396578
10
mpint.c
10
mpint.c
@ -869,11 +869,12 @@ unsigned mp_cmp_hs(mp_int *a, mp_int *b)
|
||||
unsigned mp_hs_integer(mp_int *x, uintmax_t n)
|
||||
{
|
||||
BignumInt carry = 1;
|
||||
for (size_t i = 0; i < x->nw; i++) {
|
||||
size_t nwords = sizeof(n)/BIGNUM_INT_BYTES;
|
||||
for (size_t i = 0, e = size_t_max(x->nw, nwords); i < e; i++) {
|
||||
BignumInt nword = n;
|
||||
n = shift_right_by_one_word(n);
|
||||
BignumInt dummy_out;
|
||||
BignumADC(dummy_out, carry, x->w[i], ~nword, carry);
|
||||
BignumADC(dummy_out, carry, mp_word(x, i), ~nword, carry);
|
||||
(void)dummy_out;
|
||||
}
|
||||
return carry;
|
||||
@ -895,10 +896,11 @@ unsigned mp_cmp_eq(mp_int *a, mp_int *b)
|
||||
unsigned mp_eq_integer(mp_int *x, uintmax_t n)
|
||||
{
|
||||
BignumInt diff = 0;
|
||||
for (size_t i = 0; i < x->nw; i++) {
|
||||
size_t nwords = sizeof(n)/BIGNUM_INT_BYTES;
|
||||
for (size_t i = 0, e = size_t_max(x->nw, nwords); i < e; i++) {
|
||||
BignumInt nword = n;
|
||||
n = shift_right_by_one_word(n);
|
||||
diff |= x->w[i] ^ nword;
|
||||
diff |= mp_word(x, i) ^ nword;
|
||||
}
|
||||
return 1 ^ normalise_to_1(diff); /* return 1 if diff _is_ zero */
|
||||
}
|
||||
|
@ -252,6 +252,19 @@ class mpint(MyTestBase):
|
||||
mp_max_into(am_big, am, bm)
|
||||
self.assertEqual(int(am_big), max(ai, bi))
|
||||
|
||||
# Test mp_{eq,hs}_integer in the case where the integer is as
|
||||
# large as possible and the bignum contains very few words. In
|
||||
# modes where BIGNUM_INT_BITS < 64, this used to go wrong.
|
||||
mp10 = mp_new(4)
|
||||
mp_add_integer_into(mp10, mp10, 10)
|
||||
highbit = 1 << 63
|
||||
self.assertEqual(mp_hs_integer(mp10, highbit | 9), 0)
|
||||
self.assertEqual(mp_hs_integer(mp10, highbit | 10), 0)
|
||||
self.assertEqual(mp_hs_integer(mp10, highbit | 11), 0)
|
||||
self.assertEqual(mp_eq_integer(mp10, highbit | 9), 0)
|
||||
self.assertEqual(mp_eq_integer(mp10, highbit | 10), 0)
|
||||
self.assertEqual(mp_eq_integer(mp10, highbit | 11), 0)
|
||||
|
||||
def testConditionals(self):
|
||||
testnumbers = [(mp_copy(n),n) for n in fibonacci_scattered()]
|
||||
for am, ai in testnumbers:
|
||||
|
Loading…
Reference in New Issue
Block a user