-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Open
Description
What happened?
iterator.__length_hint__ holds its internal PyMutex while calling the sequence’s __len__. A user __len__ can call back into the same __length_hint__, which immediately blocks on the already-held mutex and deadlocks the interpreter instead of raising an error or progressing the iterator.
Proof of Concept:
it = None
class Evil:
def __getitem__(self, index):
if index == 0:
return 0
raise IndexError
def __len__(self):
it.__length_hint__()
return 1
obj = Evil()
it = iter(obj)
it.__length_hint__()Affected Versions
| RustPython Version | Status | Exit Code |
|---|---|---|
Python 3.13.0alpha (heads/main-dirty:21300f689, Dec 13 2025, 22:16:49) [RustPython 0.4.0 with rustc 1.90.0-nightly (11ad40bb8 2025-06-28)] |
Deadlock | 124 |
Vulnerable Code
#[pymethod]
fn __length_hint__(&self, vm: &VirtualMachine) -> PyObjectRef {
let internal = self.internal.lock(); // holds PyMutex across user callbacks
if let IterStatus::Active(obj) = &internal.status {
let seq = PySequence { obj, methods: self.seq_methods };
seq.length(vm) // invokes user __len__. PoC calls iterator.__length_hint__ again while lock is held
.map(|x| PyInt::from(x).into_pyobject(vm))
.unwrap_or_else(|_| vm.ctx.not_implemented())
} else {
PyInt::from(0).into_pyobject(vm)
}
}
// Inner __length_hint__ call tries to lock the same mutex again, blocking forever → deadlock.Rust Output
Program hangs forever
CPython Output
Traceback (most recent call last):
File "<string>", line 15, in <module>
File "<string>", line 10, in __len__
File "<string>", line 10, in __len__
File "<string>", line 10, in __len__
[Previous line repeated 496 more times]
RecursionError: maximum recursion depth exceeded
Copilot
Metadata
Metadata
Assignees
Labels
No labels