Skip to content

Commit f4b7e9f

Browse files
committed
fixup! Fix use after free bug itertools.count()
1 parent 1068168 commit f4b7e9f

1 file changed

Lines changed: 33 additions & 27 deletions

File tree

Modules/itertoolsmodule.c

Lines changed: 33 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -3675,45 +3675,51 @@ static PyObject *
36753675
count_repr(PyObject *op)
36763676
{
36773677
countobject *lz = countobject_CAST(op);
3678-
PyObject *long_cnt, *long_step, *result;
3678+
PyObject *long_cnt, *long_step;
36793679

36803680
Py_BEGIN_CRITICAL_SECTION(lz);
36813681
long_cnt = Py_XNewRef(lz->long_cnt);
3682-
long_step = Py_XNewRef(lz->long_step);
3682+
long_step = Py_NewRef(lz->long_step);
36833683
Py_END_CRITICAL_SECTION();
36843684

36853685
if (long_cnt == NULL) {
36863686
/* Fast mode: cnt is advanced by count_next()'s lock-free atomic CAS,
3687-
which never takes this critical section, so read it atomically. */
3688-
Py_ssize_t cnt = FT_ATOMIC_LOAD_SSIZE_RELAXED(lz->cnt);
3689-
result = PyUnicode_FromFormat("%s(%zd)",
3690-
_PyType_Name(Py_TYPE(lz)), cnt);
3687+
which never takes the critical section above, so read it atomically.
3688+
Fast mode also implies that long_step is the integer 1. */
3689+
long_cnt = PyLong_FromSsize_t(FT_ATOMIC_LOAD_SSIZE_RELAXED(lz->cnt));
36913690
}
3692-
else {
3693-
int hide_step = 0;
3694-
if (PyLong_Check(long_step)) {
3695-
long step = PyLong_AsLong(long_step);
3696-
if (step == -1 && PyErr_Occurred()) {
3697-
PyErr_Clear();
3698-
}
3699-
/* Don't display step when it is an integer equal to 1 */
3700-
hide_step = (step == 1);
3701-
}
3702-
if (hide_step) {
3703-
result = PyUnicode_FromFormat("%s(%R)",
3704-
_PyType_Name(Py_TYPE(lz)),
3705-
long_cnt);
3706-
}
3707-
else {
3708-
result = PyUnicode_FromFormat("%s(%R, %R)",
3709-
_PyType_Name(Py_TYPE(lz)),
3710-
long_cnt, long_step);
3691+
3692+
/* Don't display step when it is an integer equal to 1 */
3693+
int hide_step = 0;
3694+
if (PyLong_Check(long_step)) {
3695+
long step = PyLong_AsLong(long_step);
3696+
if (step == -1 && PyErr_Occurred()) {
3697+
PyErr_Clear();
37113698
}
3699+
hide_step = (step == 1);
3700+
}
3701+
3702+
PyUnicodeWriter *writer = PyUnicodeWriter_Create(0);
3703+
int rc = (writer == NULL || long_cnt == NULL) ? -1 : 0;
3704+
if (rc == 0) {
3705+
rc = PyUnicodeWriter_Format(writer, "%s(%R",
3706+
_PyType_Name(Py_TYPE(lz)), long_cnt);
3707+
}
3708+
if (rc == 0 && !hide_step) {
3709+
rc = PyUnicodeWriter_Format(writer, ", %R", long_step);
3710+
}
3711+
if (rc == 0) {
3712+
rc = PyUnicodeWriter_WriteChar(writer, ')');
37123713
}
37133714

37143715
Py_XDECREF(long_cnt);
3715-
Py_XDECREF(long_step);
3716-
return result;
3716+
Py_DECREF(long_step);
3717+
3718+
if (rc < 0) {
3719+
PyUnicodeWriter_Discard(writer);
3720+
return NULL;
3721+
}
3722+
return PyUnicodeWriter_Finish(writer);
37173723
}
37183724

37193725
static PyType_Slot count_slots[] = {

0 commit comments

Comments
 (0)