Skip to content

Commit 750b54a

Browse files
sampsoncclaude
andcommitted
gh-145678: Strengthen test to assert refcount invariant
Use sys.getrefcount() to verify that gbo->currkey's reference to 'other' is held throughout the comparison. This makes the test fail on unpatched builds without requiring ASAN. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 5daf7c4 commit 750b54a

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

Lib/test/test_itertools.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -756,15 +756,20 @@ def keys():
756756

757757
def test_grouper_next_reentrant_eq_does_not_crash(self):
758758
# regression test for gh-145678
759+
ref_before = ref_after = None
760+
759761
class Key:
760762
def __init__(self, val, do_advance):
761763
self.val = val
762764
self.do_advance = do_advance
763765

764766
def __eq__(self, other):
767+
nonlocal ref_before, ref_after
765768
if self.do_advance:
766769
self.do_advance = False
770+
ref_before = sys.getrefcount(other)
767771
next(g)
772+
ref_after = sys.getrefcount(other)
768773
return NotImplemented
769774
return self.val == other.val
770775

@@ -775,6 +780,12 @@ def __hash__(self):
775780
g = itertools.groupby([1, 1, 2], lambda _: next(keys_iter))
776781
k, grp = next(g)
777782
list(grp) # must not crash with address sanitizer
783+
# On an unpatched build, next(g) releases gbo->currkey's reference to
784+
# 'other', so the count drops by 1 -- the object will be freed when the
785+
# __eq__ frame exits, leaving do_richcompare() with a dangling pointer.
786+
self.assertEqual(ref_before, ref_after,
787+
"gbo->currkey lost its ref to 'other' mid-comparison "
788+
"(use-after-free)")
778789

779790
def test_filter(self):
780791
self.assertEqual(list(filter(isEven, range(6))), [0,2,4])

0 commit comments

Comments
 (0)