python / python/cpython

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

Aperta
#151,673 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

Nessuno ha ancora preso questa issue.

extension-modules type-crash
Lingua principale
Python
Stelle
77.2k
Fork
35.9k
Metriche di merge delle PR
Metriche PR in attesa

Descrizione

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

Guida per i contributori

Apri la guida per i contributori

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Direzione di ricerca

Inizia in Python/_warnings.c, in setup_context() e do_warn(), soprattutto nel ramo f == NULL e nella pulizia di handle_error descritta nel report. Esegui il riproduttore Python fornito con _testcapi.set_nomemory(0, 0); il lavoro è completato quando l’emissione degli avvisi non causa più un segfault se le allocazioni falliscono, inclusi entrambi i percorsi di pulizia.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
c, python
Ambito
backend
Tipo di issue
Bug
Difficoltà
3/5
Tempo stimato
1-2 giorni
Stato di attività
Ferma
Chiarezza
Specificata chiaramente
Idoneità per principianti
35/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.