Repository navigation
tsan-006: itertoolsmodule.c: count.__repr__ plain-reads cnt #153908
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Jul 18, 2026 - addedextension-modulesC modules in the Modules dirC modules in the Modules dir
on Jul 18, 2026 - added3.14bugs and security fixesbugs and security fixes3.15bugs and security fixesbugs and security fixes3.16new features, bugs and security fixesnew features, bugs and security fixes
on Jul 18, 2026 Backports on automerge
- added a commit that references this issue
on Jul 18, 2026 After GH-153917,
itertools.count.__repr__still data-races in slow (big-int) mode.The fix hardened
count_next(fast mode: atomic CAS onlz->cnt; slow mode:count_nextlongunderPy_BEGIN_CRITICAL_SECTION(lz)) and the fast-mode read incount_repr. Butcount_repr's slow-mode path readslz->long_cntwith no synchronization — starting at theif (lz->long_cnt == NULL)mode check and again in thePyUnicode_FromFormat("%R", ..., lz->long_cnt)— whilecount_nextlongdoeslz->long_cnt = stepped_upunder the critical section. A critical section only serializes against other critical sections, socount_repr(which never takes it) still races the write. It's also a use-after-free:count_reprborrowslz->long_cntandrepr()s it, whilecount_nextlongreplaces it and the old value returned bynext()is later decref'd and freed.Repro on a free-threaded
--with-thread-sanitizerbuild (PYTHON_GIL=0):import itertools, threading NT = 8 for _ in range(3000): it = itertools.count(10**18, 2) # big-int -> slow (long_cnt) mode bar = threading.Barrier(NT) def work(advance, it=it, bar=bar): bar.wait() for _ in range(400): next(it) if advance else repr(it) ts = [threading.Thread(target=work, args=(i % 2 == 0,)) for i in range(NT)] for t in ts: t.start() for t in ts: t.join()
TSan reports
count_nextlong(lz->long_cnt = stepped_up) vscount_repr(lz->long_cntread). Fast-modecount()is clean.The fix would mirror
count_next's slow path: takePy_BEGIN_CRITICAL_SECTION(lz)aroundcount_repr'slong_cntaccess (or readlong_cntatomically).Should I open a new issue for this, or is it fine to handle it here?
@devdanzin I had already raised #153983 shortly after working on the fast mode race
@johng Ah, sorry, missed that! Your fix fully addresses the issues described above.
BTW, great work finding interesting bugs, much appreciated!
Reacted by John
Bug description:
Follows from #153852 for data race on plain read of
cntinreprCPython versions tested on:
CPython main branch
Operating systems tested on:
Macos 26.3.2
Linked PRs
itertools.count.__repr__(GH-153917) #153951itertools.count.__repr__(GH-153917) #153952