Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Use-after-free inbytearray_mod (bytes formatting) via re-entrant__repr__ method #142557

Closed
Assignees
picnixz
Labels
interpreter-core(Objects, Python, Grammar, and Parser dirs)type-crashA hard crash of the interpreter, possibly with a core dump
@jackfromeast

Description

@jackfromeast

What happened?

When formatting abytearray (the% operator) the C implementation walks the original format buffer while callingPyObject_Repr/PyObject_ASCII for%a-style conversions. A crafted object's__repr__ can clear/resize thebytearray, freeing its buffer while the C code still holds a pointer into it. Subsequent reads use a stale pointer and crash with a heap use-after-free.

Proof of Concept:

fmt=bytearray(b"%a %a")classEvil:def__repr__(self):# Re-entrant mutation: shrink the format buffer while C code# still iterates over the original pointer.fmt.clear()return"E"fmt% (Evil(),Evil())

Affected Versions:

Details
Python VersionStatusExit Code
Python 3.9.24+ (heads/3.9:9c4638d, Oct 17 2025, 11:19:30)ASAN1
Python 3.10.19+ (heads/3.10:0142619, Oct 17 2025, 11:20:05) [GCC 13.3.0]ASAN1
Python 3.11.14+ (heads/3.11:88f3f5b, Oct 17 2025, 11:20:44) [GCC 13.3.0]ASAN1
Python 3.12.12+ (heads/3.12:8cb2092, Oct 17 2025, 11:21:35) [GCC 13.3.0]ASAN1
Python 3.13.9+ (heads/3.13:0760a57, Oct 17 2025, 11:22:25) [GCC 13.3.0]ASAN1
Python 3.14.0+ (heads/3.14:889e918, Oct 17 2025, 11:23:02) [GCC 13.3.0]ASAN1
Python 3.15.0a1+ (heads/main:fbf0843, Oct 17 2025, 11:23:37) [GCC 13.3.0]ASAN1

Vulnerable Code Snippet

Details
staticPyObject*bytearray_mod(PyObject*v,PyObject*w){PyObject*ret;if (PyByteArray_Check(w)) {Py_BEGIN_CRITICAL_SECTION2(v,w);ret=bytearray_mod_lock_held(v,w);Py_END_CRITICAL_SECTION2();    }else {Py_BEGIN_CRITICAL_SECTION(v);ret=bytearray_mod_lock_held(v,w);Py_END_CRITICAL_SECTION();    }returnret;}PyObject*_PyBytes_FormatEx(constchar*format,Py_ssize_tformat_len,PyObject*args,intuse_bytearray){...sign=0;fill=' ';switch (c) {case'r':// %r is only for 2/3 code; 3 only code should use %acase'a':// Trigger the __repr__ method to free the bytearray while other bytes is still being processed in the looptemp=PyObject_ASCII(v);if (temp==NULL)            gotoerror;assert(PyUnicode_IS_ASCII(temp));pbuf= (constchar*)PyUnicode_1BYTE_DATA(temp);len=PyUnicode_GET_LENGTH(temp);if (prec >=0&&len>prec)len=prec;break;    ....}

Sanitizer

Details
===================================================================1533621==ERROR: AddressSanitizer: heap-use-after-free on address 0x503000001c12 at pc 0x64106e00f963 bp 0x7ffee0be1b40 sp 0x7ffee0be1b30READ of size 1 at 0x503000001c12 thread T0    #0 0x64106e00f962 in _PyBytes_FormatEx Objects/bytesobject.c:651    #1 0x64106dff0cf2 in bytearray_mod_lock_held Objects/bytearrayobject.c:2702    #2 0x64106dff0d33 in bytearray_mod Objects/bytearrayobject.c:2716    #3 0x64106dfdc613 in binary_op1 Objects/abstract.c:966    #4 0x64106dfdc777 in binary_op Objects/abstract.c:1005    #5 0x64106dfdfeea in PyNumber_Remainder Objects/abstract.c:1189    #6 0x64106e2878f8 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:62    #7 0x64106e2d4e54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121    #8 0x64106e2d5148 in _PyEval_Vector Python/ceval.c:2001    #9 0x64106e2d53f8 in PyEval_EvalCode Python/ceval.c:884    #10 0x64106e3cc507 in run_eval_code_obj Python/pythonrun.c:1365    #11 0x64106e3cc723 in run_mod Python/pythonrun.c:1459    #12 0x64106e3cd57a in pyrun_file Python/pythonrun.c:1293    #13 0x64106e3d0220 in _PyRun_SimpleFileObject Python/pythonrun.c:521    #14 0x64106e3d04f6 in _PyRun_AnyFileObject Python/pythonrun.c:81    #15 0x64106e42174d in pymain_run_file_obj Modules/main.c:410    #16 0x64106e4219b4 in pymain_run_file Modules/main.c:429    #17 0x64106e4231b2 in pymain_run_python Modules/main.c:691    #18 0x64106e423842 in Py_RunMain Modules/main.c:772    #19 0x64106e423a2e in pymain_main Modules/main.c:802    #20 0x64106e423db3 in Py_BytesMain Modules/main.c:826    #21 0x64106dea7645 in main Programs/python.c:15    #22 0x79ed96e2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58    #23 0x79ed96e2a28a in __libc_start_main_impl ../csu/libc-start.c:360    #24 0x64106dea7574 in _start (/home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-latest/targets/cpython/python+0x2dd574) (BuildId: ff3dc40ea460bd4beb2c3a72283cca525b319bf0)0x503000001c12 is located 18 bytes inside of 30-byte region [0x503000001c00,0x503000001c1e)freed by thread T0 here:    #0 0x79ed972fc778 in realloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:85    #1 0x64106e0da2d2 in _PyMem_RawRealloc Objects/obmalloc.c:85    #2 0x64106e0dc4e4 in _PyMem_DebugRawRealloc Objects/obmalloc.c:3010    #3 0x64106e0dc823 in _PyMem_DebugRealloc Objects/obmalloc.c:3108    #4 0x64106e1032e7 in PyMem_Realloc Objects/obmalloc.c:1063    #5 0x64106dfebc04 in bytearray_resize_lock_held Objects/bytearrayobject.c:258    #6 0x64106dff924c in PyByteArray_Resize Objects/bytearrayobject.c:278    #7 0x64106dffaf8e in bytearray_clear_impl Objects/bytearrayobject.c:1260    #8 0x64106dffafaf in bytearray_clear Objects/clinic/bytearrayobject.c.h:227    #9 0x64106e032571 in method_vectorcall_NOARGS Objects/descrobject.c:448    #10 0x64106e012e7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169    #11 0x64106e012f72 in PyObject_Vectorcall Objects/call.c:327    #12 0x64106e291056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620    #13 0x64106e2d4e54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121    #14 0x64106e2d5148 in _PyEval_Vector Python/ceval.c:2001    #15 0x64106e0129b8 in _PyFunction_Vectorcall Objects/call.c:413    #16 0x64106e012e7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169    #17 0x64106e01303f in PyObject_CallOneArg Objects/call.c:395    #18 0x64106e125648 in call_unbound_noarg Objects/typeobject.c:3040    #19 0x64106e140fa0 in maybe_call_special_no_args Objects/typeobject.c:3153    #20 0x64106e141084 in _PyObject_MaybeCallSpecialNoArgs Objects/typeobject.c:3184    #21 0x64106e14118f in slot_tp_repr Objects/typeobject.c:10546    #22 0x64106e0d0792 in PyObject_Repr Objects/object.c:779    #23 0x64106e0d228d in PyObject_ASCII Objects/object.c:842    #24 0x64106e010471 in _PyBytes_FormatEx Objects/bytesobject.c:848    #25 0x64106dff0cf2 in bytearray_mod_lock_held Objects/bytearrayobject.c:2702    #26 0x64106dff0d33 in bytearray_mod Objects/bytearrayobject.c:2716    #27 0x64106dfdc613 in binary_op1 Objects/abstract.c:966    #28 0x64106dfdc777 in binary_op Objects/abstract.c:1005    #29 0x64106dfdfeea in PyNumber_Remainder Objects/abstract.c:1189previously allocated by thread T0 here:    #0 0x79ed972fd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69    #1 0x64106e0da284 in _PyMem_RawMalloc Objects/obmalloc.c:63    #2 0x64106e0d9655 in _PyMem_DebugRawAlloc Objects/obmalloc.c:2887    #3 0x64106e0dc64f in _PyMem_DebugRawRealloc Objects/obmalloc.c:2963    #4 0x64106e0dc823 in _PyMem_DebugRealloc Objects/obmalloc.c:3108    #5 0x64106e1032e7 in PyMem_Realloc Objects/obmalloc.c:1063    #6 0x64106dfebc04 in bytearray_resize_lock_held Objects/bytearrayobject.c:258    #7 0x64106dff924c in PyByteArray_Resize Objects/bytearrayobject.c:278    #8 0x64106dff9850 in bytearray___init___impl Objects/bytearrayobject.c:978    #9 0x64106dffa2c9 in bytearray___init__ Objects/clinic/bytearrayobject.c.h:102    #10 0x64106e1393c0 in type_call Objects/typeobject.c:2460    #11 0x64106e012c71 in _PyObject_MakeTpCall Objects/call.c:242    #12 0x64106e012f19 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:167    #13 0x64106e012f72 in PyObject_Vectorcall Objects/call.c:327    #14 0x64106e291056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620    #15 0x64106e2d4e54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121    #16 0x64106e2d5148 in _PyEval_Vector Python/ceval.c:2001    #17 0x64106e2d53f8 in PyEval_EvalCode Python/ceval.c:884    #18 0x64106e3cc507 in run_eval_code_obj Python/pythonrun.c:1365    #19 0x64106e3cc723 in run_mod Python/pythonrun.c:1459    #20 0x64106e3cd57a in pyrun_file Python/pythonrun.c:1293    #21 0x64106e3d0220 in _PyRun_SimpleFileObject Python/pythonrun.c:521    #22 0x64106e3d04f6 in _PyRun_AnyFileObject Python/pythonrun.c:81    #23 0x64106e42174d in pymain_run_file_obj Modules/main.c:410    #24 0x64106e4219b4 in pymain_run_file Modules/main.c:429    #25 0x64106e4231b2 in pymain_run_python Modules/main.c:691    #26 0x64106e423842 in Py_RunMain Modules/main.c:772    #27 0x64106e423a2e in pymain_main Modules/main.c:802    #28 0x64106e423db3 in Py_BytesMain Modules/main.c:826    #29 0x64106dea7645 in main Programs/python.c:15SUMMARY: AddressSanitizer: heap-use-after-free Objects/bytesobject.c:651 in _PyBytes_FormatExShadow bytes around the buggy address:  0x503000001980: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd  0x503000001a00: fd fd fa fa fd fd fd fa fa fa fd fd fd fd fa fa  0x503000001a80: fd fd fd fd fa fa fd fd fd fa fa fa fd fd fd fd  0x503000001b00: fa fa fd fd fd fd fa fa fd fd fd fd fa fa fd fd  0x503000001b80: fd fd fa fa fd fd fd fa fa fa fd fd fd fd fa fa=>0x503000001c00: fd fd[fd]fd fa fa 00 00 00 01 fa fa fa fa fa fa  0x503000001c80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa  0x503000001d00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa  0x503000001d80: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa  0x503000001e00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa  0x503000001e80: 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==1533621==ABORTING

Linked PRs

Metadata

Metadata

Assignees

Labels

interpreter-core(Objects, Python, Grammar, and Parser dirs)type-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


    [8]ページ先頭

    ©2009-2026 Movatter.jp