Issue 13496: Fix bisect.bisect overflow bug for large collections.

This commit is contained in:
Mark Dickinson 2012-04-15 16:30:35 +01:00
parent 18e3d81f96
commit a13b109bc0
3 changed files with 18 additions and 2 deletions

View file

@ -122,6 +122,13 @@ class TestBisect(unittest.TestCase):
self.assertRaises(ValueError, mod.insort_left, [1, 2, 3], 5, -1, 3), self.assertRaises(ValueError, mod.insort_left, [1, 2, 3], 5, -1, 3),
self.assertRaises(ValueError, mod.insort_right, [1, 2, 3], 5, -1, 3), self.assertRaises(ValueError, mod.insort_right, [1, 2, 3], 5, -1, 3),
def test_large_range(self):
# Issue 13496
mod = self.module
data = range(sys.maxsize-1)
self.assertEqual(mod.bisect_left(data, sys.maxsize-3), sys.maxsize-3)
self.assertEqual(mod.bisect_right(data, sys.maxsize-3), sys.maxsize-2)
def test_random(self, n=25): def test_random(self, n=25):
from random import randrange from random import randrange
for i in range(n): for i in range(n):

View file

@ -43,6 +43,9 @@ Core and Builtins
Library Library
------- -------
- Issue #13496: Fix potential overflow in bisect.bisect algorithm when applied
to a collection of size > sys.maxsize / 2.
- Issue #14399: zipfile now recognizes that the archive has been modified even - Issue #14399: zipfile now recognizes that the archive has been modified even
if only the comment is changed. In addition, the TypeError that results from if only the comment is changed. In addition, the TypeError that results from
trying to set a non-binary value as a comment is now now raised at the time trying to set a non-binary value as a comment is now now raised at the time

View file

@ -21,7 +21,10 @@ internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t
return -1; return -1;
} }
while (lo < hi) { while (lo < hi) {
mid = (lo + hi) / 2; /* The (size_t)cast ensures that the addition and subsequent division
are performed as unsigned operations, avoiding difficulties from
signed overflow. (See issue 13496.) */
mid = ((size_t)lo + hi) / 2;
litem = PySequence_GetItem(list, mid); litem = PySequence_GetItem(list, mid);
if (litem == NULL) if (litem == NULL)
return -1; return -1;
@ -121,7 +124,10 @@ internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t h
return -1; return -1;
} }
while (lo < hi) { while (lo < hi) {
mid = (lo + hi) / 2; /* The (size_t)cast ensures that the addition and subsequent division
are performed as unsigned operations, avoiding difficulties from
signed overflow. (See issue 13496.) */
mid = ((size_t)lo + hi) / 2;
litem = PySequence_GetItem(list, mid); litem = PySequence_GetItem(list, mid);
if (litem == NULL) if (litem == NULL)
return -1; return -1;