Repository navigation
Heap-buffer-overflow in _decimal_exec via overriding collections.namedtuple #142595
Copy link
Copy link
Closed
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Description
What happened?
_decimal_exec calls collections.namedtuple("DecimalTuple", ...) and assumes it returns a type. If collections.namedtuple has been set to return a non-type object, the code casts it to PyTypeObject* and writes to tp_dict (__module__), causing type confusion and a heap buffer overflow during module initialization.
Proof of Concept:
import collections
collections.namedtuple = lambda *a, **k: object()
import _decimalAffected Versions:
| Python Version | Status | Exit Code |
|---|---|---|
Python 3.9.24+ (heads/3.9:9c4638d, Oct 17 2025, 11:19:30) |
ASAN | 1 |
Python 3.10.19+ (heads/3.10:0142619, Oct 17 2025, 11:20:05) [GCC 13.3.0] |
ASAN | 1 |
Python 3.11.14+ (heads/3.11:88f3f5b, Oct 17 2025, 11:20:44) [GCC 13.3.0] |
ASAN | 1 |
Python 3.12.12+ (heads/3.12:8cb2092, Oct 17 2025, 11:21:35) [GCC 13.3.0] |
ASAN | 1 |
Python 3.13.9+ (heads/3.13:0760a57, Oct 17 2025, 11:22:25) [GCC 13.3.0] |
ASAN | 1 |
Python 3.14.0+ (heads/3.14:889e918, Oct 17 2025, 11:23:02) [GCC 13.3.0] |
ASAN | 1 |
Python 3.15.0a1+ (heads/main:fbf0843, Oct 17 2025, 11:23:37) [GCC 13.3.0] |
Exception | 1 |
Vulnerable Code:
cpython/Modules/_decimal/_decimal.c:7646-7651
ASSIGN_PTR(state->DecimalTuple, (PyTypeObject *)PyObject_CallMethod(collections,
"namedtuple", "(ss)", "DecimalTuple",
"sign digits exponent"));
ASSIGN_PTR(obj, PyUnicode_FromString("decimal"));
CHECK_INT(PyDict_SetItemString(state->DecimalTuple->tp_dict, "__module__", obj));
Py_CLEAR(obj);Sanitizer Output
(base) jackfromeast@blue-sea:~/Desktop/entropy/tasks/grammar-afl++-latest/targets/cpython$ /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython-afl/bin/python3 /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-latest/inputs/decimal_poc.py
=================================================================
==863339==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x504000004c68 at pc 0x728e1ca00bd7 bp 0x7ffe94ca42c0 sp 0x7ffe94ca42b8
READ of size 8 at 0x504000004c68 thread T0
#0 0x728e1ca00bd6 in _decimal_exec /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Modules/_decimal/_decimal.c:6001:5
#1 0x5d68c379ab3f in PyModule_ExecDef /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/moduleobject.c:495:23
#2 0x5d68c3dbab12 in exec_builtin_or_dynamic /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/import.c:817:12
#3 0x5d68c3dbab12 in _imp_exec_dynamic_impl /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/import.c:4745:12
#4 0x5d68c3dbab12 in _imp_exec_dynamic /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/clinic/import.c.h:514:21
#5 0x5d68c3790ab8 in cfunction_vectorcall_O /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/methodobject.c:523:24
#6 0x5d68c3c0493f in _PyEval_EvalFrameDefault /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/generated_cases.c.h:1758:32
#7 0x5d68c3bdfd22 in _PyEval_EvalFrame /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Include/internal/pycore_ceval.h:116:16
#8 0x5d68c3bdfd22 in _PyEval_Vector /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/ceval.c:1911:12
#9 0x5d68c35a05be in _PyObject_VectorcallTstate /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Include/internal/pycore_call.h:167:11
#10 0x5d68c35a05be in object_vacall /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/call.c:819:14
#11 0x5d68c359faa4 in PyObject_CallMethodObjArgs /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/call.c:880:24
#12 0x5d68c3da6987 in import_find_and_load /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/import.c:3681:11
#13 0x5d68c3da6987 in PyImport_ImportModuleLevelObject /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/import.c:3763:15
#14 0x5d68c3c4f02a in _PyEval_ImportName /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/ceval.c:2812:16
#15 0x5d68c3be2937 in _PyEval_EvalFrameDefault /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/generated_cases.c.h:4359:31
#16 0x5d68c3bdfd22 in _PyEval_EvalFrame /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Include/internal/pycore_ceval.h:116:16
#17 0x5d68c3bdfd22 in _PyEval_Vector /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/ceval.c:1911:12
#18 0x5d68c3bdedf8 in PyEval_EvalCode /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/ceval.c:658:21
#19 0x5d68c3ed05b7 in run_eval_code_obj /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/pythonrun.c:1338:9
#20 0x5d68c3ece010 in run_mod /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/pythonrun.c:1423:19
#21 0x5d68c3ebfca1 in pyrun_file /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/pythonrun.c:1256:15
#22 0x5d68c3ebfca1 in _PyRun_SimpleFileObject /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/pythonrun.c:491:13
#23 0x5d68c3ebe49f in _PyRun_AnyFileObject /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/pythonrun.c:78:15
#24 0x5d68c3f99e97 in pymain_run_file_obj /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:410:15
#25 0x5d68c3f99e97 in pymain_run_file /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:429:15
#26 0x5d68c3f957b9 in pymain_run_python /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:697:21
#27 0x5d68c3f957b9 in Py_RunMain /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:776:5
#28 0x5d68c3f9740c in pymain_main /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:806:12
#29 0x5d68c3f975d6 in Py_BytesMain /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:830:12
#30 0x728e1ec2a1c9 in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16
#31 0x728e1ec2a28a in __libc_start_main csu/../csu/libc-start.c:360:3
#32 0x5d68c3225144 in _start (/home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython-afl/bin/python3.14+0x259144) (BuildId: 4a021c7c2d7561e34d5f3a67f13e279fba070d79)
0x504000004c68 is located 240 bytes after 40-byte region [0x504000004b50,0x504000004b78)
allocated by thread T0 here:
#0 0x5d68c32bff93 in malloc (/home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython-afl/bin/python3.14+0x2f3f93) (BuildId: 4a021c7c2d7561e34d5f3a67f13e279fba070d79)
#1 0x5d68c381ab3e in _PyMem_DebugRawAlloc /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/obmalloc.c:2733:24
#2 0x5d68c381ab3e in _PyMem_DebugRawMalloc /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/obmalloc.c:2766:12
#3 0x5d68c381ab3e in _PyMem_DebugMalloc /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/obmalloc.c:2930:12
#4 0x5d68c388bb49 in _PyObject_MallocWithType /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Include/internal/pycore_object_alloc.h:46:17
#5 0x5d68c388bb49 in _PyType_AllocNoTrack /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/typeobject.c:2229:19
#6 0x5d68c388b8ac in PyType_GenericAlloc /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/typeobject.c:2258:21
#7 0x5d68c38a0c89 in type_call /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/typeobject.c:2173:11
#8 0x5d68c3596a76 in _PyObject_MakeTpCall /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/call.c:242:18
#9 0x5d68c3c181a7 in _PyEval_EvalFrameDefault /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/generated_cases.c.h:960:35
#10 0x5d68c3bdfd22 in _PyEval_EvalFrame /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Include/internal/pycore_ceval.h:116:16
#11 0x5d68c3bdfd22 in _PyEval_Vector /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/ceval.c:1911:12
#12 0x5d68c359c14a in _PyObject_VectorcallTstate /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Include/internal/pycore_call.h:167:11
#13 0x5d68c359c14a in _PyObject_CallFunctionVa /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/call.c
#14 0x5d68c359cf14 in callmethod /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/call.c:626:12
#15 0x5d68c359cf14 in PyObject_CallMethod /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/call.c:645:24
#16 0x728e1c9fe3a2 in _decimal_exec /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Modules/_decimal/_decimal.c:5996:5
#17 0x5d68c379ab3f in PyModule_ExecDef /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/moduleobject.c:495:23
#18 0x5d68c3dbab12 in exec_builtin_or_dynamic /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/import.c:817:12
#19 0x5d68c3dbab12 in _imp_exec_dynamic_impl /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/import.c:4745:12
#20 0x5d68c3dbab12 in _imp_exec_dynamic /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/clinic/import.c.h:514:21
#21 0x5d68c3790ab8 in cfunction_vectorcall_O /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/methodobject.c:523:24
#22 0x5d68c3c0493f in _PyEval_EvalFrameDefault /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/generated_cases.c.h:1758:32
#23 0x5d68c3bdfd22 in _PyEval_EvalFrame /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Include/internal/pycore_ceval.h:116:16
#24 0x5d68c3bdfd22 in _PyEval_Vector /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/ceval.c:1911:12
#25 0x5d68c35a05be in _PyObject_VectorcallTstate /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Include/internal/pycore_call.h:167:11
#26 0x5d68c35a05be in object_vacall /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/call.c:819:14
#27 0x5d68c359faa4 in PyObject_CallMethodObjArgs /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Objects/call.c:880:24
#28 0x5d68c3da6987 in import_find_and_load /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/import.c:3681:11
#29 0x5d68c3da6987 in PyImport_ImportModuleLevelObject /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/import.c:3763:15
#30 0x5d68c3c4f02a in _PyEval_ImportName /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/ceval.c:2812:16
#31 0x5d68c3be2937 in _PyEval_EvalFrameDefault /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/generated_cases.c.h:4359:31
#32 0x5d68c3bdfd22 in _PyEval_EvalFrame /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Include/internal/pycore_ceval.h:116:16
#33 0x5d68c3bdfd22 in _PyEval_Vector /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/ceval.c:1911:12
#34 0x5d68c3bdedf8 in PyEval_EvalCode /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/ceval.c:658:21
#35 0x5d68c3ed05b7 in run_eval_code_obj /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/pythonrun.c:1338:9
#36 0x5d68c3ece010 in run_mod /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/pythonrun.c:1423:19
#37 0x5d68c3ebfca1 in pyrun_file /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/pythonrun.c:1256:15
#38 0x5d68c3ebfca1 in _PyRun_SimpleFileObject /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/pythonrun.c:491:13
#39 0x5d68c3ebe49f in _PyRun_AnyFileObject /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Python/pythonrun.c:78:15
#40 0x5d68c3f99e97 in pymain_run_file_obj /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:410:15
#41 0x5d68c3f99e97 in pymain_run_file /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:429:15
#42 0x5d68c3f957b9 in pymain_run_python /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:697:21
#43 0x5d68c3f957b9 in Py_RunMain /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:776:5
#44 0x5d68c3f9740c in pymain_main /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/Modules/main.c:806:12
SUMMARY: AddressSanitizer: heap-buffer-overflow /home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-issue-128049/targets/cpython/./Modules/_decimal/_decimal.c:6001:5 in _decimal_exec
Shadow bytes around the buggy address:
0x504000004980: fa fa 00 00 00 00 00 fa fa fa 00 00 00 00 00 07
0x504000004a00: fa fa 00 00 00 00 00 00 fa fa fd fd fd fd fd fd
0x504000004a80: fa fa fd fd fd fd fd fa fa fa fd fd fd fd fd fd
0x504000004b00: fa fa fd fd fd fd fd fa fa fa 00 00 00 00 00 fa
0x504000004b80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
=>0x504000004c00: fa fa fa fa fa fa fa fa fa fa fa fa fa[fa]fa fa
0x504000004c80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000004d00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000004d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000004e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x504000004e80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow 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
==863339==ABORTINGLinked PRs
- gh-142595: add type check for namedtuple call during decimal initialization #142608
- [3.13] gh-142595: add type check for namedtuple call during decimal initialization (GH-142608) #142622
- [3.14] gh-142595: add type check for namedtuple call during decimal initialization (GH-142608) #142623
- gh-142595: Amend be5e0dcdedb (fix NULL pointer dereference) #142775
- [3.14] gh-142595: Amend be5e0dcdedb (fix NULL pointer dereference) (GH-142775) #142788
- [3.13] gh-142595: Amend be5e0dcdedb (fix NULL pointer dereference) (GH-142775) #142789
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtype-crashA hard crash of the interpreter, possibly with a core dumpA hard crash of the interpreter, possibly with a core dump
Activity
pythongh-142595: add type check for namedtuple call during decimal in…
skirpichev commentedon Dec 12, 2025
#142608 is available for review.
Though, this looks to be rather artificial problem. There are also other ways to break stdlib to violate assumptions during the decimal initialization. (But nothing else to introduce a crash.)
CC @serhiy-storchaka
gh-142595: add type check for namedtuple call during decimal initiali…
pythongh-142595: add type check for namedtuple call during decimal in…
pythongh-142595: add type check for namedtuple call during decimal in…
[3.14] gh-142595: add type check for namedtuple call during decimal i…
[3.13] gh-142595: add type check for namedtuple call during decimal i…
encukou commentedon Dec 15, 2025
Thank you @jackfromeast for the report and @skirpichev for the fix!
serhiy-storchaka commentedon Dec 15, 2025
#142608 introduced another bug.
pythongh-142595: Amend be5e0dc (fix NULL pointer dereference)
gh-142595: Amend be5e0dc (fix NULL pointer dereference) (GH-142775)
pythongh-142595: Amend be5e0dc (fix NULL pointer dereference) (python…
pythongh-142595: Amend be5e0dc (fix NULL pointer dereference) (python…
pythongh-142595: Amend be5e0dc (fix NULL pointer dereference) (python…
[3.14] gh-142595: Amend be5e0dc (fix NULL pointer dereference) (GH-14…
[3.13] gh-142595: Amend be5e0dc (fix NULL pointer dereference) (GH-14…