Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 39a86c2

Browse files
committed
SF bug 555042: zip() may trigger MemoryError.
NOT a bugfix candidate: this is a fix to an optimization introduced in 2.3.
1 parent 9b1df1d commit 39a86c2

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

Lib/test/test_b2.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,17 @@ class G:
344344
if not exc:
345345
raise TestFailed, 'zip(a, b) - missing expected TypeError'
346346

347+
# Make sure zip doesn't try to allocate a billion elements for the
348+
# result list when one of its arguments doesn't say how long it is.
349+
# A MemoryError is the most likely failure mode.
350+
class SequenceWithoutALength:
351+
def __getitem__(self, i):
352+
if i == 5:
353+
raise IndexError
354+
else:
355+
return i
356+
vereq(zip(SequenceWithoutALength(), xrange(2**30)),
357+
list(enumerate(range(5))))
347358

348359
# Epilogue -- unlink the temp file
349-
350360
unlink(TESTFN)

Python/bltinmodule.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1717,13 +1717,18 @@ builtin_zip(PyObject *self, PyObject *args)
17171717
/* args must be a tuple */
17181718
assert(PyTuple_Check(args));
17191719

1720-
/* Guess at result length: the shortest of the input lengths. */
1720+
/* Guess at result length: the shortest of the input lengths.
1721+
If some argument refuses to say, we refuse to guess too, lest
1722+
an argument like xrange(sys.maxint) lead us astray.*/
17211723
len = -1; /* unknown */
17221724
for (i = 0; i < itemsize; ++i) {
17231725
PyObject *item = PyTuple_GET_ITEM(args, i);
17241726
int thislen = PySequence_Length(item);
1725-
if (thislen < 0)
1727+
if (thislen < 0) {
17261728
PyErr_Clear();
1729+
len = -1;
1730+
break;
1731+
}
17271732
else if (len < 0 || thislen < len)
17281733
len = thislen;
17291734
}

0 commit comments

Comments
 (0)