python / python/cpython

dir() can crash with cyclic __bases__

Open
#155,452 15 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

interpreter-core pending type-crash
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Crash report

What happened?

dir() can cause a native stack overflow when an object's __class__
provides a cyclic __bases__ attribute.

Minimal reproducer:

class Fake:
    pass

a = Fake()
a.__bases__ = (a,)

class C:
    @property
    def __class__(self):
        return a

print("entering", flush=True)
dir(C())
print("survived", flush=True)
Observed Result

On CPython 3.16.0a0 built from commit 5107fd700d7:

entering
timeout: the monitored command dumped core
Segmentation fault
rc=139

The crash occurs because object.__dir__() obtains the object's __class__ and merge_class_dict() recursively traverses __bases__ without a recursion guard. A cyclic __bases__ therefore causes unbounded native recursion and eventually a SIGSEGV.

The analogous __bases__ traversal in abstract_issubclass() already uses _Py_EnterRecursiveCall().

I also verified that adding a recursion guard to merge_class_dict() changes the failure from a native crash to a catchable exception:

RecursionError: Stack overflow (used 8120 kB) in __bases__

A regression test covering the cyclic __bases__ case was also added to Lib/test/test_builtin.py and passes with:

./python -m test test_builtin -m test_dir
== Tests result: SUCCESS ==
1 test OK.
CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Output from running 'python -VV' on the command line:

Python 3.16.0a0 (heads/investigate-0071-dir-cyclic-bases-dirty:5107fd700d7, Aug 9 2026, 21:10:20) [GCC 13.3.0]

Linked PRs
  • gh-155453

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with merge_class_dict() and the cyclic bases reproducer described in the issue, then read the regression test in Lib/test/test_builtin.py. Run ./python -m test test_builtin -m test_dir; done means the case raises a catchable RecursionError instead of causing a native stack overflow.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.