]> granicus.if.org Git - python/commitdiff
Issue 13496: Fix bisect.bisect overflow bug for large collections.
authorMark Dickinson <mdickinson@enthought.com>
Sun, 15 Apr 2012 15:43:19 +0000 (16:43 +0100)
committerMark Dickinson <mdickinson@enthought.com>
Sun, 15 Apr 2012 15:43:19 +0000 (16:43 +0100)
Lib/test/test_bisect.py
Misc/NEWS
Modules/_bisectmodule.c

index 934ba8c7a10bde1e5342c59a58ba776bb8ae78d1..4f004d2213f34b3e84cd685027ca9444ba02513d 100644 (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_right, [1, 2, 3], 5, -1, 3),
 
+    def test_large_range(self):
+        # Issue 13496
+        mod = self.module
+        data = xrange(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):
         from random import randrange
         for i in xrange(n):
index 85bea30b3ecf6b12145793cce739d867f9d1f031..ec27d20152cb8fe41038bee1ae1e4c41b4a4ee81 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -48,6 +48,9 @@ Core and Builtins
 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
   if only the comment is changed.  As a consequence of this fix, ZipFile is now
   a new style class.
index e8976b24053d5bb760c9dfd5a0510b1e38bb0568..4798c124eefa10e6fb36aeaf451a70b80441130f 100644 (file)
@@ -21,7 +21,13 @@ internal_bisect_right(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t
             return -1;
     }
     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.) */
+        printf("lo: %d\n", lo);
+        printf("hi: %d\n", hi);
+        printf("mid: %d\n", mid);
+        mid = ((size_t)lo + hi) / 2;
         litem = PySequence_GetItem(list, mid);
         if (litem == NULL)
             return -1;
@@ -122,7 +128,10 @@ internal_bisect_left(PyObject *list, PyObject *item, Py_ssize_t lo, Py_ssize_t h
             return -1;
     }
     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);
         if (litem == NULL)
             return -1;