mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
k_mul(): White-box testing turned up that (ah+al)*(bh+bl) can, in rare
cases, overflow the allocated result object by 1 bit. In such cases, it would have been brought back into range if we subtracted al*bl and ah*bh from it first, but I don't want to do that because it hurts cache behavior. Instead we just ignore the excess bit when it appears -- in effect, this is forcing unsigned mod BASE**(asize + bsize) arithmetic in a case where that doesn't happen all by itself.
This commit is contained in:
parent
3747a0f04c
commit
d8b2173ef9
1 changed files with 11 additions and 3 deletions
|
@ -1663,7 +1663,7 @@ k_mul(PyLongObject *a, PyLongObject *b)
|
|||
*/
|
||||
|
||||
/* 1. Allocate result space. */
|
||||
ret = _PyLong_New(asize + bsize);
|
||||
ret = _PyLong_New(asize + bsize + 1);
|
||||
if (ret == NULL) goto fail;
|
||||
#ifdef Py_DEBUG
|
||||
/* Fill with trash, to catch reference to uninitialized digits. */
|
||||
|
@ -1727,7 +1727,15 @@ k_mul(PyLongObject *a, PyLongObject *b)
|
|||
Py_DECREF(t2);
|
||||
if (t3 == NULL) goto fail;
|
||||
|
||||
/* Add t3. */
|
||||
/* Add t3. Caution: t3 can spill one bit beyond the allocated
|
||||
* result space; it's t3-al*bl-ah*bh that always fits. We have
|
||||
* to arrange to ignore the hight bit.
|
||||
*/
|
||||
if (t3->ob_size > i) {
|
||||
assert(t3->ob_size == i+1); /* just one digit over */
|
||||
assert(t3->ob_digit[t3->ob_size - 1] == 1); /* & just one bit */
|
||||
--t3->ob_size; /* ignore the overflow bit */
|
||||
}
|
||||
(void)v_iadd(ret->ob_digit + shift, i, t3->ob_digit, t3->ob_size);
|
||||
Py_DECREF(t3);
|
||||
|
||||
|
@ -1761,7 +1769,7 @@ long_mul(PyLongObject *v, PyLongObject *w)
|
|||
return Py_NotImplemented;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
if (Py_GETENV("KARAT") != NULL)
|
||||
z = k_mul(a, b);
|
||||
else
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue