Skip to content

Commit e898626

Browse files
gh-143543: Fix re-entrant use-after-free in itertools.groupby
1 parent a6bc60d commit e898626

File tree

2 files changed

+26
-1
lines changed

2 files changed

+26
-1
lines changed

Lib/test/test_itertools.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,22 @@ def keyfunc(obj):
733733
keyfunc.skip = 1
734734
self.assertRaises(ExpectedError, gulp, [None, None], keyfunc)
735735

736+
def test_groupby_reentrant_eq_does_not_crash(self):
737+
738+
class Key(bytearray):
739+
seen = False
740+
def __eq__(self, other):
741+
if not Key.seen:
742+
Key.seen = True
743+
next(g)
744+
return False
745+
746+
data = [Key(b"a"), Key(b"b")]
747+
748+
g = itertools.groupby(data)
749+
next(g)
750+
next(g) # must not segfault
751+
736752
def test_filter(self):
737753
self.assertEqual(list(filter(isEven, range(6))), [0,2,4])
738754
self.assertEqual(list(filter(None, [0,1,0,2,0])), [1,2])

Modules/itertoolsmodule.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,8 +545,17 @@ groupby_next(PyObject *op)
545545
break;
546546
else {
547547
int rcmp;
548+
PyObject *tgtkey = gbo->tgtkey;
549+
PyObject *currkey = gbo->currkey;
548550

549-
rcmp = PyObject_RichCompareBool(gbo->tgtkey, gbo->currkey, Py_EQ);
551+
Py_INCREF(tgtkey);
552+
Py_INCREF(currkey);
553+
554+
rcmp = PyObject_RichCompareBool(tgtkey, currkey, Py_EQ);
555+
556+
Py_DECREF(tgtkey);
557+
Py_DECREF(currkey);
558+
550559
if (rcmp == -1)
551560
return NULL;
552561
else if (rcmp == 0)

0 commit comments

Comments
 (0)