Commit a13b109b authored by Mark Dickinson's avatar Mark Dickinson

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

parent 18e3d81f
...@@ -122,6 +122,13 @@ class TestBisect(unittest.TestCase): ...@@ -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):
......
...@@ -43,6 +43,9 @@ Core and Builtins ...@@ -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
......
...@@ -21,7 +21,10 @@ internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t ...@@ -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 ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment