python / python/cpython

Segfault: `Py_DECREF(NULL)` in `setup_context`/`do_warn` (`_warnings.c`) when emitting a warning under MemoryError

Open
#151,673 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

extension-modules type-crash
Dominant language
Python
Stars
77.2k
Forks
35.9k
PR merge metrics
PR metrics pending

Description

Crash report

What happened?

AI Disclaimer: this issue was drafted by Claude Code, which also generated the reduced reproducer.

Emitting a warning while allocations are failing segfaults on a Py_DECREF of a NULL filename. setup_context() does not NULL-check PyUnicode_FromString("<sys>"), and the resulting NULL is later decref'd either by do_warn() (success path) or by setup_context()'s own handle_error: label (which uses Py_DECREF, not Py_XDECREF).

Reproducer

import _testcapi, warnings, faulthandler
faulthandler.enable()
warnings.simplefilter("always")
_testcapi.set_nomemory(0, 0)   # fail every allocation from here on
warnings.warn("boom")          # -> Py_DECREF(NULL) -> SIGSEGV

Deterministic (start=0). Reproduced on main.

Backtrace

#0 _Py_atomic_load_uint32_relaxed   Include/cpython/pyatomic_gcc.h
#1 Py_DECREF                        Include/refcount.h
#2 do_warn                          Python/_warnings.c:1139   <- Py_DECREF(filename), filename == NULL
#3 warnings_warn_impl               Python/_warnings.c:1184
#4 warnings_warn                    Python/clinic/_warnings.c.h:161

(gdb) frame 2; print filename$1 = (PyObject *) 0x0.

Root cause

In setup_context() (_warnings.c), the f == NULL branch (~L1036):

if (f == NULL) {
    globals = interp->sysdict;
    *filename = PyUnicode_FromString("<sys>");   /* return value unchecked */
    *lineno = 0;
}

Under memory pressure two allocations fail in sequence:

  1. PyThreadState_GetFrame() returns NULL (its frame-object allocation fails), so the f == NULL branch is taken; then
  2. PyUnicode_FromString("<sys>") itself returns NULL, leaving *filename == NULL.

The NULL *filename then reaches a Py_DECREF:

  • if setup_context() returns success (registry and __name__ already present in globals, so no further allocation is needed), do_warn() runs its cleanup Py_DECREF(filename) at L1139 — NULL deref; or
  • if setup_context() instead hits handle_error: (L1084), that path runs Py_DECREF(*filename) (L1087, not Py_XDECREF) — NULL deref.

Suggested fix

    *filename = PyUnicode_FromString("<sys>");
    if (*filename == NULL) {
        goto handle_error;
    }

and at handle_error: use Py_XDECREF(*filename) (since *filename may legitimately be NULL there).

Notes

Found by OOM-injection fuzzing (set_nomemory). Same pattern as gh-146080 (Py_DECREF(NULL) in an _ssl.c error label). Code is long-standing, so 3.13–3.15 are likely affected as well (unverified).

Found using fusil by @vstinner.

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/main:bfecfcc2a86, Jun 18 2026, 13:48:35) [Clang 22.1.2 (1ubuntu1)]

Linked PRs
  • gh-151767
  • gh-154715

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 in Python/_warnings.c at setup_context() and do_warn(), especially the f == NULL branch and the handle_error cleanup described in the report. Run the supplied Python reproducer with _testcapi.set_nomemory(0, 0); done means warning emission no longer segfaults when allocations fail, including both cleanup paths.

Written by the indexing model from the issue text.

Assessment

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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.