Bug description
itertools.count has a use-after-free when the step object's __radd__ re-enters the iterator via next().
count_nextlong() borrows lz->long_cnt without Py_INCREF, then calls PyNumber_Add(result, lz->long_step). If long_step.__radd__ calls next() on the same count, the inner call returns the same pointer and the caller frees it. The outer call then returns a dangling pointer.
Crashes with PYTHONMALLOC=debug (SIGSEGV).
import itertools
class Step:
def __radd__(self, other):
next(c)
return other + 1
c = itertools.count(1 << 100, Step())
next(c) # SIGSEGV
CPython versions tested on
main
Operating systems tested on
macOS
Linked PRs
Bug description
itertools.counthas a use-after-free when the step object's__radd__re-enters the iterator vianext().count_nextlong()borrowslz->long_cntwithoutPy_INCREF, then callsPyNumber_Add(result, lz->long_step). Iflong_step.__radd__callsnext()on the same count, the inner call returns the same pointer and the caller frees it. The outer call then returns a dangling pointer.Crashes with
PYTHONMALLOC=debug(SIGSEGV).CPython versions tested on
main
Operating systems tested on
macOS
Linked PRs