Commit 748b8bbe authored by Tim Peters's avatar Tim Peters

Fix buglet reported on c.l.py: map(fnc, file.xreadlines()) blows up.

Also a 2.1 bugfix candidate (am I supposed to do something with those?).
Took away map()'s insistence that sequences support __len__, and cleaned
up the convoluted code that made it *look* like it really cared about
__len__ (in fact the old ->len field was only *used* as a flag bit, as
the main loop only looked at its sign bit, setting the field to -1 when
IndexError got raised; renamed the field to ->saw_IndexError instead).
parent b3d8d1f7
...@@ -816,10 +816,10 @@ builtin_execfile(PyObject *self, PyObject *args) ...@@ -816,10 +816,10 @@ builtin_execfile(PyObject *self, PyObject *args)
if (PyEval_GetNestedScopes()) { if (PyEval_GetNestedScopes()) {
PyCompilerFlags cf; PyCompilerFlags cf;
cf.cf_nested_scopes = 1; cf.cf_nested_scopes = 1;
res = PyRun_FileExFlags(fp, filename, Py_file_input, globals, res = PyRun_FileExFlags(fp, filename, Py_file_input, globals,
locals, 1, &cf); locals, 1, &cf);
} else } else
res = PyRun_FileEx(fp, filename, Py_file_input, globals, res = PyRun_FileEx(fp, filename, Py_file_input, globals,
locals, 1); locals, 1);
return res; return res;
} }
...@@ -924,7 +924,7 @@ builtin_map(PyObject *self, PyObject *args) ...@@ -924,7 +924,7 @@ builtin_map(PyObject *self, PyObject *args)
typedef struct { typedef struct {
PyObject *seq; PyObject *seq;
PySequenceMethods *sqf; PySequenceMethods *sqf;
int len; int saw_IndexError;
} sequence; } sequence;
PyObject *func, *result; PyObject *func, *result;
...@@ -952,6 +952,10 @@ builtin_map(PyObject *self, PyObject *args) ...@@ -952,6 +952,10 @@ builtin_map(PyObject *self, PyObject *args)
goto Fail_2; goto Fail_2;
} }
/* Do a first pass to (a) verify the args are sequences; (b) set
* len to the largest of their lengths; (c) initialize the seqs
* descriptor vector.
*/
for (len = 0, i = 0, sqp = seqs; i < n; ++i, ++sqp) { for (len = 0, i = 0, sqp = seqs; i < n; ++i, ++sqp) {
int curlen; int curlen;
PySequenceMethods *sqf; PySequenceMethods *sqf;
...@@ -959,9 +963,10 @@ builtin_map(PyObject *self, PyObject *args) ...@@ -959,9 +963,10 @@ builtin_map(PyObject *self, PyObject *args)
if ((sqp->seq = PyTuple_GetItem(args, i + 1)) == NULL) if ((sqp->seq = PyTuple_GetItem(args, i + 1)) == NULL)
goto Fail_2; goto Fail_2;
sqp->saw_IndexError = 0;
sqp->sqf = sqf = sqp->seq->ob_type->tp_as_sequence; sqp->sqf = sqf = sqp->seq->ob_type->tp_as_sequence;
if (sqf == NULL || if (sqf == NULL ||
sqf->sq_length == NULL ||
sqf->sq_item == NULL) sqf->sq_item == NULL)
{ {
static char errmsg[] = static char errmsg[] =
...@@ -973,9 +978,13 @@ builtin_map(PyObject *self, PyObject *args) ...@@ -973,9 +978,13 @@ builtin_map(PyObject *self, PyObject *args)
goto Fail_2; goto Fail_2;
} }
if ((curlen = sqp->len = (*sqp->sqf->sq_length)(sqp->seq)) < 0) if (sqf->sq_length == NULL)
/* doesn't matter -- make something up */
curlen = 8;
else
curlen = (*sqf->sq_length)(sqp->seq);
if (curlen < 0)
goto Fail_2; goto Fail_2;
if (curlen > len) if (curlen > len)
len = curlen; len = curlen;
} }
...@@ -983,6 +992,7 @@ builtin_map(PyObject *self, PyObject *args) ...@@ -983,6 +992,7 @@ builtin_map(PyObject *self, PyObject *args)
if ((result = (PyObject *) PyList_New(len)) == NULL) if ((result = (PyObject *) PyList_New(len)) == NULL)
goto Fail_2; goto Fail_2;
/* Iterate over the sequences until all have raised IndexError. */
for (i = 0; ; ++i) { for (i = 0; ; ++i) {
PyObject *alist, *item=NULL, *value; PyObject *alist, *item=NULL, *value;
int any = 0; int any = 0;
...@@ -995,7 +1005,7 @@ builtin_map(PyObject *self, PyObject *args) ...@@ -995,7 +1005,7 @@ builtin_map(PyObject *self, PyObject *args)
} }
for (j = 0, sqp = seqs; j < n; ++j, ++sqp) { for (j = 0, sqp = seqs; j < n; ++j, ++sqp) {
if (sqp->len < 0) { if (sqp->saw_IndexError) {
Py_INCREF(Py_None); Py_INCREF(Py_None);
item = Py_None; item = Py_None;
} }
...@@ -1008,7 +1018,7 @@ builtin_map(PyObject *self, PyObject *args) ...@@ -1008,7 +1018,7 @@ builtin_map(PyObject *self, PyObject *args)
PyErr_Clear(); PyErr_Clear();
Py_INCREF(Py_None); Py_INCREF(Py_None);
item = Py_None; item = Py_None;
sqp->len = -1; sqp->saw_IndexError = 1;
} }
else { else {
goto Fail_0; goto Fail_0;
......
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