mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
Constraint: Python-level sentinel equality can re-enter the same callable iterator while internal iterator state is protected by a non-reentrant lock. Rejected: Holding the callable iterator status lock across sentinel equality | user-defined __eq__ can call next() on the same iterator and deadlock. Confidence: high Scope-risk: moderate Tested: pre-commit run --all-files; cargo test --workspace --exclude rustpython_wasm --exclude rustpython-venvlauncher; cargo build --release --features sqlite; pytest -v in extra_tests; cargo run --quiet -- extra_tests/snippets/protocol_iternext.py; cargo check -p rustpython-vm; cargo clippy -p rustpython-vm --all-targets -- -D warnings; git diff --check Not-tested: push/PR creation Assisted-by: Codex:gpt-5.5
46 lines
1005 B
Python
46 lines
1005 B
Python
ls = [1, 2, 3]
|
|
|
|
i = iter(ls)
|
|
assert i.__next__() == 1
|
|
assert i.__next__() == 2
|
|
assert next(i) == 3
|
|
|
|
assert next(i, "w00t") == "w00t"
|
|
|
|
s = "你好"
|
|
i = iter(s)
|
|
i.__setstate__(1)
|
|
assert i.__next__() == "好"
|
|
assert i.__reduce__()[2] == 2
|
|
|
|
|
|
# Regression test for re-entrant callable iterator sentinel equality.
|
|
# Equality can execute Python code that calls back into the same iterator.
|
|
class ReenterEq:
|
|
entered = False
|
|
it = None
|
|
|
|
def __eq__(self, other):
|
|
if not self.entered:
|
|
self.entered = True
|
|
try:
|
|
next(self.it)
|
|
except StopIteration:
|
|
pass
|
|
else:
|
|
raise AssertionError("inner next should stop at the sentinel")
|
|
return True
|
|
|
|
|
|
value = ReenterEq()
|
|
sentinel = object()
|
|
callable_it = iter(lambda: value, sentinel)
|
|
value.it = callable_it
|
|
try:
|
|
next(callable_it)
|
|
except StopIteration:
|
|
pass
|
|
else:
|
|
raise AssertionError("outer next should stop at the sentinel")
|
|
assert value.entered
|