Crash report
What happened?
Since gh-139482 (PR gh-139965, October 2025) os.environ.clear() calls posix._clearenv() →
clearenv(3). On glibc clearenv() sets the global environ to NULL rather than to an
empty array. Any C library that walks environ without a NULL check then segfaults; Tcl is one
of them (TclSetupEnv in generic/tclEnv.c reads environ[0], in 8.6 and on Tcl main).
Before this change clear() removed keys one at a time with unsetenv(), which leaves
environ a valid empty array, and the program below worked.
The following code:
import os
os.environ.clear()
import tkinter
tkinter.Tcl()
Resulted in this output:
AddressSanitizer:DEADLYSIGNAL
==1527921==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x75e7d758a13f bp 0x78b7d9e5f060 sp 0x7ffdab0f82c0 T0)
==1527921==The signal is caused by a READ memory access.
==1527921==Hint: address points to the zero page.
#0 0x75e7d758a13f in TclSetupEnv (/lib/x86_64-linux-gnu/libtcl8.6.so+0xb213f)
#1 0x75e7d75114d8 in Tcl_CreateInterp (/lib/x86_64-linux-gnu/libtcl8.6.so+0x394d8)
#2 0x75e7d88c1607 in Tkapp_New Modules/_tkinter.c:643:17
#3 0x75e7d88c1607 in _tkinter_create_impl Modules/_tkinter.c:3483:25
#4 0x75e7d88c1607 in _tkinter_create Modules/clinic/_tkinter.c.h:898:20
#5 0x6375e0068750 in cfunction_vectorcall_FASTCALL Objects/methodobject.c:449:24
#6 0x6375dfeb5205 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144:11
#7 0x6375e04005ac in _Py_VectorCallInstrumentation_StackRefSteal Python/ceval.c:770:11
#8 0x6375e0449521 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1906:35
#9 0x6375e03ff857 in _PyEval_Vector Python/ceval.c:2176:12
#10 0x6375dfeb55b4 in _PyObject_VectorcallDictTstate Objects/call.c:135:15
#11 0x6375dfeb97e6 in _PyObject_Call_Prepend Objects/call.c:504:24
#12 0x6375e017d7b0 in call_method Objects/typeobject.c:3070:19
#13 0x6375e01c9165 in slot_tp_init Objects/typeobject.c:11115:21
#14 0x6375e0159c7a in type_call Objects/typeobject.c:2454:19
Without a sanitizer it is a plain Segmentation fault. It is deterministic.
Evidence that the NULL pointer is the cause:
import os, ctypes
environ = ctypes.c_void_p.in_dll(ctypes.CDLL(None), "environ")
os.environ.clear()
print(environ.value) # None -> environ == NULL
Deleting the keys individually instead keeps environ non-NULL and tkinter.Tcl() succeeds:
import os
for k in list(os.environ):
del os.environ[k]
import tkinter
tkinter.Tcl() # OK
Calling libc.clearenv() directly from ctypes reproduces the crash too, so the library
behaviour is glibc's; the regression is that os.environ.clear() now exposes it to every
tkinter (and any other environ-walking extension) user. Possible fixes on the CPython side:
after clearenv(), point environ at a static {NULL} array (glibc's setenv/putenv copy
rather than realloc an environ they did not allocate, so this is safe), or fall back to the
per-key unsetenv() loop.
To reproduce:
Commit:
e682b4478c2ad09de0bbe821127f451f02f6e5ca (main, 2026-09-16)
Build configuration:
../configure --with-pydebug --enable-experimental-jit=yes --with-address-sanitizer --with-undefined-behavior-sanitizer
Operating System:
Ubuntu 22.04.5 LTS, x86_64, glibc 2.35, Tcl/Tk 8.6.12 (libtcl8.6 8.6.12+dfsg-1build1), in Docker (image fusion-fuzz-cpython:latest)
This bug was found by fusion-fuzz
CPython versions tested on:
CPython main branch
Operating systems tested on:
No response
Output from running 'python -VV' on the command line:
No response
Linked PRs
Crash report
What happened?
Since gh-139482 (PR gh-139965, October 2025)
os.environ.clear()callsposix._clearenv()→clearenv(3). On glibcclearenv()sets the globalenvironto NULL rather than to anempty array. Any C library that walks
environwithout a NULL check then segfaults; Tcl is oneof them (
TclSetupEnvin generic/tclEnv.c readsenviron[0], in 8.6 and on Tclmain).Before this change
clear()removed keys one at a time withunsetenv(), which leavesenvirona valid empty array, and the program below worked.The following code:
Resulted in this output:
Without a sanitizer it is a plain
Segmentation fault. It is deterministic.Evidence that the NULL pointer is the cause:
Deleting the keys individually instead keeps
environnon-NULL andtkinter.Tcl()succeeds:Calling
libc.clearenv()directly from ctypes reproduces the crash too, so the librarybehaviour is glibc's; the regression is that
os.environ.clear()now exposes it to everytkinter (and any other
environ-walking extension) user. Possible fixes on the CPython side:after
clearenv(), pointenvironat a static{NULL}array (glibc'ssetenv/putenvcopyrather than realloc an
environthey did not allocate, so this is safe), or fall back to theper-key
unsetenv()loop.To reproduce:
Commit:
Build configuration:
Operating System:
This bug was found by fusion-fuzz
CPython versions tested on:
CPython main branch
Operating systems tested on:
No response
Output from running 'python -VV' on the command line:
No response
Linked PRs