]> granicus.if.org Git - python/commitdiff
SF bug 555042: zip() may trigger MemoryError.
authorTim Peters <tim.peters@gmail.com>
Sun, 12 May 2002 07:19:38 +0000 (07:19 +0000)
committerTim Peters <tim.peters@gmail.com>
Sun, 12 May 2002 07:19:38 +0000 (07:19 +0000)
NOT a bugfix candidate:  this is a fix to an optimization introduced
in 2.3.

Lib/test/test_b2.py
Python/bltinmodule.c

index 72810cbf2b6edf300b2958ed218289a76ac78e91..459fd6b851a9737865da89e6d44f2168f21bf89e 100644 (file)
@@ -344,7 +344,17 @@ except:
 if not exc:
     raise TestFailed, 'zip(a, b) - missing expected TypeError'
 
+# Make sure zip doesn't try to allocate a billion elements for the
+# result list when one of its arguments doesn't say how long it is.
+# A MemoryError is the most likely failure mode.
+class SequenceWithoutALength:
+    def __getitem__(self, i):
+        if i == 5:
+            raise IndexError
+        else:
+            return i
+vereq(zip(SequenceWithoutALength(), xrange(2**30)),
+      list(enumerate(range(5))))
 
 # Epilogue -- unlink the temp file
-
 unlink(TESTFN)
index fb6810edb8d94de2e2acb20ca335f3486214ab8b..d0411e23ae74dcfe2803f80bd65a5b0f0e085b98 100644 (file)
@@ -1717,13 +1717,18 @@ builtin_zip(PyObject *self, PyObject *args)
        /* args must be a tuple */
        assert(PyTuple_Check(args));
 
-       /* Guess at result length:  the shortest of the input lengths. */
+       /* Guess at result length:  the shortest of the input lengths.
+          If some argument refuses to say, we refuse to guess too, lest
+          an argument like xrange(sys.maxint) lead us astray.*/
        len = -1;       /* unknown */
        for (i = 0; i < itemsize; ++i) {
                PyObject *item = PyTuple_GET_ITEM(args, i);
                int thislen = PySequence_Length(item);
-               if (thislen < 0)
+               if (thislen < 0) {
                        PyErr_Clear();
+                       len = -1;
+                       break;
+               }
                else if (len < 0 || thislen < len)
                        len = thislen;
        }