From c740e4fe8a9bc5815dc18c38d7f7600b128c3c51 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 26 Sep 2017 21:47:56 +0300 Subject: bpo-30347: Stop crashes when concurrently iterate over itertools.groupby() iterators. (#1557) --- Modules/itertoolsmodule.c | 67 ++++++++++++++++++++++------------------------- 1 file changed, 31 insertions(+), 36 deletions(-) (limited to 'Modules/itertoolsmodule.c') diff --git a/Modules/itertoolsmodule.c b/Modules/itertoolsmodule.c index cc9895a942..9190236364 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); -- cgit v1.2.1