Skip to content

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

Description

@devdanzin

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

Activity

  1. added
    type-crashA hard crash of the interpreter, possibly with a core dump
    on Jun 18, 2026
  2. added a commit that references this issue on Jun 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirtype-crashA hard crash of the interpreter, possibly with a core dump

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions