Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork34k
Closed
Description
What happened?
POP_TOP finalizes an object whose__del__ raises, invokingsys.unraisablehook.format_unraisable_v calls the hook re-entrantly, then decref's it before reusing the pointer as the fallbackobj. When the hook raises (freeing the partial),write_unraisable_exc_file tries to repr the danglingobj, hitting a heap use-after-free in_Py_TYPE.
Proof of Concept:
importsysimportfunctoolsdeftakeover(unraisable):sys.unraisablehook=sys.__unraisablehook__raiseRuntimeError("hook failure")sys.unraisablehook=functools.partial(takeover)classBoom:def__del__(self):raiseValueError("boom")Boom()
Vulnerable Code Snippet:
Click to expand
/* Buggy Re-entrant Path */pureinst(POP_TOP, (value--)) {PyStackRef_XCLOSE(value);}staticvoidformat_unraisable_v(constchar*format,va_listva,PyObject*obj){/* ... */PyObject*res=PyObject_CallOneArg(hook,hook_args);/* Reentrant call site */Py_DECREF(hook);Py_DECREF(hook_args);if (res!=NULL) {/* ... */ gotodone; }/* sys.unraisablehook failed: log its error using default hook */obj=hook;/* crashing pointer derived *//* ... */ (void)write_unraisable_exc(tstate,exc_type,exc_value,exc_tb,err_msg,obj);}staticintwrite_unraisable_exc_file(PyThreadState*tstate,PyObject*exc_type,PyObject*exc_value,PyObject*exc_tb,PyObject*err_msg,PyObject*obj,PyObject*file){/* ... */if (PyFile_WriteObject(obj,file,0)<0) {/* Crash site */_PyErr_Clear(tstate); }/* ... */return0;}staticinlinePyTypeObject*_Py_TYPE(PyObject*ob){returnob->ob_type;/* Crash site */}/* Clobbering Path */staticvoidpartial_dealloc(PyObject*self){PyTypeObject*tp=Py_TYPE(self);/* ... */tp->tp_free(self);/* state mutate site */Py_DECREF(tp);}
Sanitizer Output:
Click to expand
===================================================================71182==ERROR: AddressSanitizer: heap-use-after-free on address 0x5080000234b8 at pc 0x58b4baa5e1d5 bp 0x7fffb29a0520 sp 0x7fffb29a0510READ of size 8 at 0x5080000234b8 thread T0 #0 0x58b4baa5e1d4 in _Py_TYPE Include/object.h:277 #1 0x58b4baa5e1d4 in PyObject_Repr Objects/object.c:761 #2 0x58b4ba99d32c in PyFile_WriteObject Objects/fileobject.c:122 #3 0x58b4bad20902 in write_unraisable_exc_file Python/errors.c:1472 #4 0x58b4bad2a94f in write_unraisable_exc Python/errors.c:1605 #5 0x58b4bad2a94f in format_unraisable_v Python/errors.c:1752 #6 0x58b4bad2cd04 in PyErr_FormatUnraisable Python/errors.c:1769 #7 0x58b4baaeaa90 in slot_tp_finalize Objects/typeobject.c:10874 #8 0x58b4baa5f270 in PyObject_CallFinalizer Objects/object.c:585 #9 0x58b4baa5f270 in PyObject_CallFinalizerFromDealloc Objects/object.c:603 #10 0x58b4baad12d0 in subtype_dealloc Objects/typeobject.c:2774 #11 0x58b4baa5d1d8 in _Py_Dealloc Objects/object.c:3200 #12 0x58b4ba7f5e28 in Py_DECREF_MORTAL Include/internal/pycore_object.h:482 #13 0x58b4ba7f5e28 in PyStackRef_CLOSE Include/internal/pycore_stackref.h:707 #14 0x58b4ba7f5e28 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:10110 #15 0x58b4bacbead6 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121 #16 0x58b4bacbead6 in _PyEval_Vector Python/ceval.c:2001 #17 0x58b4bacbead6 in PyEval_EvalCode Python/ceval.c:884 #18 0x58b4bae0416e in run_eval_code_obj Python/pythonrun.c:1365 #19 0x58b4bae0416e in run_mod Python/pythonrun.c:1459 #20 0x58b4bae08e17 in pyrun_file Python/pythonrun.c:1293 #21 0x58b4bae08e17 in _PyRun_SimpleFileObject Python/pythonrun.c:521 #22 0x58b4bae0993c in _PyRun_AnyFileObject Python/pythonrun.c:81 #23 0x58b4bae7ce3c in pymain_run_file_obj Modules/main.c:410 #24 0x58b4bae7ce3c in pymain_run_file Modules/main.c:429 #25 0x58b4bae7ce3c in pymain_run_python Modules/main.c:691 #26 0x58b4bae7e71e in Py_RunMain Modules/main.c:772 #27 0x58b4bae7e71e in pymain_main Modules/main.c:802 #28 0x58b4bae7e71e in Py_BytesMain Modules/main.c:826 #29 0x7b090a02a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #30 0x7b090a02a28a in __libc_start_main_impl ../csu/libc-start.c:360 #31 0x58b4ba818634 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x206634) (BuildId: 4d105290d0ad566a4d6f4f7b2f05fbc9e317b533)0x5080000234b8 is located 24 bytes inside of 96-byte region [0x5080000234a0,0x508000023500)freed by thread T0 here: #0 0x7b090a4fc4d8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52 #1 0x58b4bafdcadf in partial_dealloc Modules/_functoolsmodule.c:350 #2 0x58b4baa5d1d8 in _Py_Dealloc Objects/object.c:3200 #3 0x58b4bad2b493 in Py_DECREF Include/refcount.h:418 #4 0x58b4bad2b493 in format_unraisable_v Python/errors.c:1730 #5 0x58b4bad2cd04 in PyErr_FormatUnraisable Python/errors.c:1769 #6 0x58b4baaeaa90 in slot_tp_finalize Objects/typeobject.c:10874 #7 0x58b4baa5f270 in PyObject_CallFinalizer Objects/object.c:585 #8 0x58b4baa5f270 in PyObject_CallFinalizerFromDealloc Objects/object.c:603 #9 0x58b4baad12d0 in subtype_dealloc Objects/typeobject.c:2774 #10 0x58b4baa5d1d8 in _Py_Dealloc Objects/object.c:3200 #11 0x58b4ba7f5e28 in Py_DECREF_MORTAL Include/internal/pycore_object.h:482 #12 0x58b4ba7f5e28 in PyStackRef_CLOSE Include/internal/pycore_stackref.h:707 #13 0x58b4ba7f5e28 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:10110 #14 0x58b4bacbead6 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121 #15 0x58b4bacbead6 in _PyEval_Vector Python/ceval.c:2001 #16 0x58b4bacbead6 in PyEval_EvalCode Python/ceval.c:884 #17 0x58b4bae0416e in run_eval_code_obj Python/pythonrun.c:1365 #18 0x58b4bae0416e in run_mod Python/pythonrun.c:1459 #19 0x58b4bae08e17 in pyrun_file Python/pythonrun.c:1293 #20 0x58b4bae08e17 in _PyRun_SimpleFileObject Python/pythonrun.c:521 #21 0x58b4bae0993c in _PyRun_AnyFileObject Python/pythonrun.c:81 #22 0x58b4bae7ce3c in pymain_run_file_obj Modules/main.c:410 #23 0x58b4bae7ce3c in pymain_run_file Modules/main.c:429 #24 0x58b4bae7ce3c in pymain_run_python Modules/main.c:691 #25 0x58b4bae7e71e in Py_RunMain Modules/main.c:772 #26 0x58b4bae7e71e in pymain_main Modules/main.c:802 #27 0x58b4bae7e71e in Py_BytesMain Modules/main.c:826 #28 0x7b090a02a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #29 0x7b090a02a28a in __libc_start_main_impl ../csu/libc-start.c:360 #30 0x58b4ba818634 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x206634) (BuildId: 4d105290d0ad566a4d6f4f7b2f05fbc9e317b533)previously allocated by thread T0 here: #0 0x7b090a4fd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69 #1 0x58b4baae588e in _PyObject_MallocWithType Include/internal/pycore_object_alloc.h:46 #2 0x58b4baae588e in _PyType_AllocNoTrack Objects/typeobject.c:2504 #3 0x58b4baae5af4 in PyType_GenericAlloc Objects/typeobject.c:2535 #4 0x58b4bafd9952 in partial_new Modules/_functoolsmodule.c:226 #5 0x58b4baadd118 in type_call Objects/typeobject.c:2448 #6 0x58b4ba93e9cd in _PyObject_MakeTpCall Objects/call.c:242 #7 0x58b4ba7f45a2 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620 #8 0x58b4bacbead6 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121 #9 0x58b4bacbead6 in _PyEval_Vector Python/ceval.c:2001 #10 0x58b4bacbead6 in PyEval_EvalCode Python/ceval.c:884 #11 0x58b4bae0416e in run_eval_code_obj Python/pythonrun.c:1365 #12 0x58b4bae0416e in run_mod Python/pythonrun.c:1459 #13 0x58b4bae08e17 in pyrun_file Python/pythonrun.c:1293 #14 0x58b4bae08e17 in _PyRun_SimpleFileObject Python/pythonrun.c:521 #15 0x58b4bae0993c in _PyRun_AnyFileObject Python/pythonrun.c:81 #16 0x58b4bae7ce3c in pymain_run_file_obj Modules/main.c:410 #17 0x58b4bae7ce3c in pymain_run_file Modules/main.c:429 #18 0x58b4bae7ce3c in pymain_run_python Modules/main.c:691 #19 0x58b4bae7e71e in Py_RunMain Modules/main.c:772 #20 0x58b4bae7e71e in pymain_main Modules/main.c:802 #21 0x58b4bae7e71e in Py_BytesMain Modules/main.c:826 #22 0x7b090a02a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #23 0x7b090a02a28a in __libc_start_main_impl ../csu/libc-start.c:360 #24 0x58b4ba818634 in _start (/home/jackfromeast/Desktop/entropy/targets/grammar-afl++-latest/targets/cpython/python+0x206634) (BuildId: 4d105290d0ad566a4d6f4f7b2f05fbc9e317b533)SUMMARY: AddressSanitizer: heap-use-after-free Include/object.h:277 in _Py_TYPEShadow bytes around the buggy address: 0x508000023200: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa 0x508000023280: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 00 0x508000023300: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 00 0x508000023380: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 03 fa 0x508000023400: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd=>0x508000023480: fa fa fa fa fd fd fd[fd]fd fd fd fd fd fd fd fd 0x508000023500: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa 0x508000023580: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fa 0x508000023600: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa 0x508000023680: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 00 fa 0x508000023700: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa faShadow byte legend (one shadow byte represents 8 application bytes): Addressable: 00 Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: fa Freed heap region: fd Stack left redzone: f1 Stack mid redzone: f2 Stack right redzone: f3 Stack after return: f5 Stack use after scope: f8 Global redzone: f9 Global init order: f6 Poisoned by user: f7 Container overflow: fc Array cookie: ac Intra object redzone: bb ASan internal: fe Left alloca redzone: ca Right alloca redzone: cb==71182==ABORTINGCPython versions tested on:
Details
| Python Version | Status | Exit Code |
|---|---|---|
Python 3.9.24+ (heads/3.9:111bbc15b26, Oct 28 2025, 16:51:20) | ASAN | 1 |
Python 3.10.19+ (heads/3.10:014261980b1, Oct 28 2025, 16:52:08) [Clang 18.1.3 (1ubuntu1)] | ASAN | 1 |
Python 3.11.14+ (heads/3.11:88f3f5b5f11, Oct 28 2025, 16:53:08) [Clang 18.1.3 (1ubuntu1)] | ASAN | 1 |
Python 3.12.12+ (heads/3.12:8cb2092bd8c, Oct 28 2025, 16:54:14) [Clang 18.1.3 (1ubuntu1)] | ASAN | 1 |
Python 3.13.9+ (heads/3.13:9c8eade20c6, Oct 28 2025, 16:55:18) [Clang 18.1.3 (1ubuntu1)] | ASAN | 1 |
Python 3.14.0+ (heads/3.14:2e216728038, Oct 28 2025, 16:56:16) [Clang 18.1.3 (1ubuntu1)] | ASAN | 1 |
Python 3.15.0a1+ (heads/main:f5394c257ce, Oct 28 2025, 19:29:54) [GCC 13.3.0] | ASAN | 1 |
Operating systems tested on:
Linux
Output from running 'python -VV' on the command line:
Python 3.15.0a1+ (heads/main:f5394c257ce, Oct 28 2025, 19:29:54) [GCC 13.3.0]