Skip to content

Deadlock when __len__ re-enters __length_hint__ via list iterator #6590

@jackfromeast

Description

@jackfromeast

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

Metadata

Metadata

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions