mirror of
https://github.com/python/cpython.git
synced 2025-09-30 12:21:51 +00:00
[3.6] bpo-30347: Stop crashes when concurrently iterate over itertools.groupby() iterators. (GH-1557) (#3770)
(cherry picked from commit c740e4fe8a
)
This commit is contained in:
parent
d6a356209a
commit
69b2dc8637
3 changed files with 56 additions and 36 deletions
|
@ -1984,6 +1984,30 @@ class RegressionTests(unittest.TestCase):
|
||||||
with self.assertRaises(StopIteration):
|
with self.assertRaises(StopIteration):
|
||||||
next(it)
|
next(it)
|
||||||
|
|
||||||
|
def test_issue30347_1(self):
|
||||||
|
def f(n):
|
||||||
|
if n == 5:
|
||||||
|
list(b)
|
||||||
|
return n != 6
|
||||||
|
for (k, b) in groupby(range(10), f):
|
||||||
|
list(b) # shouldn't crash
|
||||||
|
|
||||||
|
def test_issue30347_2(self):
|
||||||
|
class K:
|
||||||
|
def __init__(self, v):
|
||||||
|
pass
|
||||||
|
def __eq__(self, other):
|
||||||
|
nonlocal i
|
||||||
|
i += 1
|
||||||
|
if i == 1:
|
||||||
|
next(g, None)
|
||||||
|
return True
|
||||||
|
i = 0
|
||||||
|
g = next(groupby(range(10), K))[1]
|
||||||
|
for j in range(2):
|
||||||
|
next(g, None) # shouldn't crash
|
||||||
|
|
||||||
|
|
||||||
class SubclassWithKwargsTest(unittest.TestCase):
|
class SubclassWithKwargsTest(unittest.TestCase):
|
||||||
def test_keywords_in_subclass(self):
|
def test_keywords_in_subclass(self):
|
||||||
# count is not subclassable...
|
# count is not subclassable...
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Stop crashes when concurrently iterate over itertools.groupby() iterators.
|
|
@ -72,10 +72,37 @@ groupby_traverse(groupbyobject *gbo, visitproc visit, void *arg)
|
||||||
return 0;
|
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 *
|
static PyObject *
|
||||||
groupby_next(groupbyobject *gbo)
|
groupby_next(groupbyobject *gbo)
|
||||||
{
|
{
|
||||||
PyObject *newvalue, *newkey, *r, *grouper;
|
PyObject *r, *grouper;
|
||||||
|
|
||||||
/* skip to next iteration group */
|
/* skip to next iteration group */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
|
@ -93,25 +120,9 @@ groupby_next(groupbyobject *gbo)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
newvalue = PyIter_Next(gbo->it);
|
if (groupby_step(gbo) < 0)
|
||||||
if (newvalue == NULL)
|
|
||||||
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Py_XSETREF(gbo->currkey, newkey);
|
|
||||||
Py_XSETREF(gbo->currvalue, newvalue);
|
|
||||||
}
|
|
||||||
|
|
||||||
Py_INCREF(gbo->currkey);
|
Py_INCREF(gbo->currkey);
|
||||||
Py_XSETREF(gbo->tgtkey, gbo->currkey);
|
Py_XSETREF(gbo->tgtkey, gbo->currkey);
|
||||||
|
|
||||||
|
@ -282,28 +293,12 @@ static PyObject *
|
||||||
_grouper_next(_grouperobject *igo)
|
_grouper_next(_grouperobject *igo)
|
||||||
{
|
{
|
||||||
groupbyobject *gbo = (groupbyobject *)igo->parent;
|
groupbyobject *gbo = (groupbyobject *)igo->parent;
|
||||||
PyObject *newvalue, *newkey, *r;
|
PyObject *r;
|
||||||
int rcmp;
|
int rcmp;
|
||||||
|
|
||||||
if (gbo->currvalue == NULL) {
|
if (gbo->currvalue == NULL) {
|
||||||
newvalue = PyIter_Next(gbo->it);
|
if (groupby_step(gbo) < 0)
|
||||||
if (newvalue == NULL)
|
|
||||||
return NULL;
|
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);
|
assert(gbo->currkey != NULL);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue