gh-145678: Fix use-after-free in itertools.groupby _grouper_next()#145679
gh-145678: Fix use-after-free in itertools.groupby _grouper_next()#145679sampsonc wants to merge 8 commits intopython:mainfrom
Conversation
_grouper_next() passed igo->tgtkey and gbo->currkey directly to PyObject_RichCompareBool() without first holding strong references. A re-entrant __eq__ that advanced the parent groupby iterator would call groupby_step(), which executes Py_XSETREF(gbo->currkey, newkey), freeing currkey while it was still under comparison. Fix by taking INCREF'd local snapshots before the comparison, mirroring the protection added to groupby_next() in pythongh-143543. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
eb0bb61 to
79bcea0
Compare
|
The two CI failures (Windows free-threading arm64 and Docs) are pre-existing issues in main unrelated to this PR. The docs check-warnings.py script confirmed zero new warnings from our changes, and the Windows failure is ENV_CHANGED from test_multiprocessing_spawn.test_threads. |
Misc/NEWS.d/next/Library/2026-03-09-00-00-00.gh-issue-145678.grouper-uaf.rst
Outdated
Show resolved
Hide resolved
|
I've been away for a couple of days. Is there anything else that I can do on this one? Thanks! |
Please address the feedback first. I would also suggest that you are aware of https://devguide.python.org/getting-started/generative-ai/ in order to avoid back-and-forth. |
Use a single variable `g` instead of `outer_grouper`/`g`, matching the style of the sibling test test_groupby_reentrant_eq_does_not_crash. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The iterator is never exhausted at this point, so StopIteration cannot be raised. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
…rouper-uaf.rst Co-authored-by: Petr Viktorin <encukou@gmail.com>
|
All feedback has been addressed. |
| @@ -0,0 +1,3 @@ | |||
| Fix a use-after-free crash in :func:`itertools.groupby` when a user-defined | |||
| ``__eq__`` advanced the parent iterator while the iterator of groups was advanced. | |||
| The fix mirrors the protection added in :gh:`143543` for ``groupby_next()``. | |||
There was a problem hiding this comment.
| The fix mirrors the protection added in :gh:`143543` for ``groupby_next()``. |
| Fix a use-after-free crash in :func:`itertools.groupby` when a user-defined | ||
| ``__eq__`` advanced the parent iterator while the iterator of groups was advanced. |
There was a problem hiding this comment.
| Fix a use-after-free crash in :func:`itertools.groupby` when a user-defined | |
| ``__eq__`` advanced the parent iterator while the iterator of groups was advanced. | |
| Fix a use-after-free crash in :func:`itertools.groupby` when the | |
| parent iterator is mutated while the iterator of groups was advanced. |
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
Fixes a use-after-free (UAF) in
_grouper_next()inModules/itertoolsmodule.c.Root Cause
_grouper_next()passedigo->tgtkeyandgbo->currkeydirectly toPyObject_RichCompareBool()without first holding strong references.A user-defined
__eq__can re-enter the parentgroupbyiterator duringthe comparison. That re-entry calls
groupby_step(), which executes:This frees
gbo->currkeywhile it is still under comparison — a use-after-free.Fix
Take INCREF'd local snapshots before calling
PyObject_RichCompareBool(),mirroring the protection added to
groupby_next()in gh-143543:Test plan
./python -m test test_itertools -k test_grouper_next_reentrant_eq_does_not_crash./configure --with-pydebug && makewith ASAN enabled) to confirm no UAFCloses gh-145678.
🤖 Generated with Claude Code