diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2017-09-26 18:47:56 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-09-26 18:47:56 (GMT) |
commit | c740e4fe8a9bc5815dc18c38d7f7600b128c3c51 (patch) | |
tree | 6edda52b98ac544e918d237abc2d2f60d185861b /Modules/itertoolsmodule.c | |
parent | 114454e9f6addbcb364e9a37102c8131ae2da1dd (diff) | |
download | cpython-c740e4fe8a9bc5815dc18c38d7f7600b128c3c51.zip cpython-c740e4fe8a9bc5815dc18c38d7f7600b128c3c51.tar.gz cpython-c740e4fe8a9bc5815dc18c38d7f7600b128c3c51.tar.bz2 |
bpo-30347: Stop crashes when concurrently iterate over itertools.groupby() iterators. (#1557)
Diffstat (limited to 'Modules/itertoolsmodule.c')
-rw-r--r-- | Modules/itertoolsmodule.c | 67 |
1 files changed, 31 insertions, 36 deletions
diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index cc9895a..9190236 100644 --- a/Modules/itertoolsmodule.c +++ b/Modules/itertoolsmodule.c @@ -73,10 +73,37 @@ groupby_traverse(groupbyobject *gbo, visitproc visit, void *arg) return 0; } +Py_LOCAL_INLINE(int) +groupby_step(groupbyobject *gbo) +{ + PyObject *newvalue, *newkey, *oldvalue; + + newvalue = PyIter_Next(gbo->it); + if (newvalue == NULL) + return -1; + + if (gbo->keyfunc == Py_None) { + newkey = newvalue; + Py_INCREF(newvalue); + } else { + newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, newvalue, NULL); + if (newkey == NULL) { + Py_DECREF(newvalue); + return -1; + } + } + + oldvalue = gbo->currvalue; + gbo->currvalue = newvalue; + Py_XSETREF(gbo->currkey, newkey); + Py_XDECREF(oldvalue); + return 0; +} + static PyObject * groupby_next(groupbyobject *gbo) { - PyObject *newvalue, *newkey, *r, *grouper; + PyObject *r, *grouper; gbo->currgrouper = NULL; /* skip to next iteration group */ @@ -95,25 +122,9 @@ groupby_next(groupbyobject *gbo) break; } - newvalue = PyIter_Next(gbo->it); - if (newvalue == NULL) + if (groupby_step(gbo) < 0) return NULL; - - if (gbo->keyfunc == Py_None) { - newkey = newvalue; - Py_INCREF(newvalue); - } else { - newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, newvalue, NULL); - if (newkey == NULL) { - Py_DECREF(newvalue); - return NULL; - } - } - - Py_XSETREF(gbo->currkey, newkey); - Py_XSETREF(gbo->currvalue, newvalue); } - Py_INCREF(gbo->currkey); Py_XSETREF(gbo->tgtkey, gbo->currkey); @@ -285,30 +296,14 @@ static PyObject * _grouper_next(_grouperobject *igo) { groupbyobject *gbo = (groupbyobject *)igo->parent; - PyObject *newvalue, *newkey, *r; + PyObject *r; int rcmp; if (gbo->currgrouper != igo) return NULL; if (gbo->currvalue == NULL) { - newvalue = PyIter_Next(gbo->it); - if (newvalue == NULL) + if (groupby_step(gbo) < 0) return NULL; - - if (gbo->keyfunc == Py_None) { - newkey = newvalue; - Py_INCREF(newvalue); - } else { - newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, newvalue, NULL); - if (newkey == NULL) { - Py_DECREF(newvalue); - return NULL; - } - } - - assert(gbo->currkey == NULL); - gbo->currkey = newkey; - gbo->currvalue = newvalue; } assert(gbo->currkey != NULL); |