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 inOrderedDict.copy via re-entrant__get_item__ #142734

Open
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?

OrderedDict.copy() iterates its nodes and calls__getitem__ to fetch values. A re-entrant__getitem__ that callsclear() during iteration frees all_ODictNode structures while_odict_FOREACH continues accessing them, resulting in a heap-use-after-free inOrderedDict_copy_impl.

Proof of Concept:

fromcollectionsimportOrderedDictclassEvil(OrderedDict):def__getitem__(self,key):super().clear()returnNone# TriggerEvil([(i,i)foriinrange(4)]).copy()

Affected Versions:

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

Relevent Code Snippets

staticPyObject*OrderedDict_copy_impl(PyObject*od)/*[clinic end generated code: output=9cdbe7394aecc576 input=e329951ae617ed48]*/{_ODictNode*node;PyObject*od_copy;if (PyODict_CheckExact(od))od_copy=PyODict_New();elseod_copy=_PyObject_CallNoArgs((PyObject*)Py_TYPE(od));if (od_copy==NULL)returnNULL;if (PyODict_CheckExact(od)) {_odict_FOREACH(od,node) {PyObject*key=_odictnode_KEY(node);PyObject*value=_odictnode_VALUE(node,od);if (value==NULL) {if (!PyErr_Occurred())PyErr_SetObject(PyExc_KeyError,key);                gotofail;            }if (_PyODict_SetItem_KnownHash_LockHeld((PyObject*)od_copy,key,value,_odictnode_HASH(node))!=0)                gotofail;        }    }else {_odict_FOREACH(od,node) {intres;// Trigger the __getitem__ and clear the array buffer so that all the node are freedPyObject*value=PyObject_GetItem((PyObject*)od,_odictnode_KEY(node));if (value==NULL)                gotofail;// Bug: Access the freed node bufferres=PyObject_SetItem((PyObject*)od_copy,_odictnode_KEY(node),value);Py_DECREF(value);if (res!=0)                gotofail;        }    }returnod_copy;fail:Py_DECREF(od_copy);returnNULL;}

Sanitizer Output:

===================================================================1546618==ERROR: AddressSanitizer: heap-use-after-free on address 0x506000063ff0 at pc 0x5b4c98be21ee bp 0x7fff1abcc980 sp 0x7fff1abcc970READ of size 8 at 0x506000063ff0 thread T0    #0 0x5b4c98be21ed in OrderedDict_copy_impl Objects/odictobject.c:1276    #1 0x5b4c98be2289 in OrderedDict_copy Objects/clinic/odictobject.c.h:377    #2 0x5b4c98b5f571 in method_vectorcall_NOARGS Objects/descrobject.c:448    #3 0x5b4c98b3fe7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169    #4 0x5b4c98b3ff72 in PyObject_Vectorcall Objects/call.c:327    #5 0x5b4c98dbe056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620    #6 0x5b4c98e01e54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121    #7 0x5b4c98e02148 in _PyEval_Vector Python/ceval.c:2001    #8 0x5b4c98e023f8 in PyEval_EvalCode Python/ceval.c:884    #9 0x5b4c98ef9507 in run_eval_code_obj Python/pythonrun.c:1365    #10 0x5b4c98ef9723 in run_mod Python/pythonrun.c:1459    #11 0x5b4c98efa57a in pyrun_file Python/pythonrun.c:1293    #12 0x5b4c98efd220 in _PyRun_SimpleFileObject Python/pythonrun.c:521    #13 0x5b4c98efd4f6 in _PyRun_AnyFileObject Python/pythonrun.c:81    #14 0x5b4c98f4e74d in pymain_run_file_obj Modules/main.c:410    #15 0x5b4c98f4e9b4 in pymain_run_file Modules/main.c:429    #16 0x5b4c98f501b2 in pymain_run_python Modules/main.c:691    #17 0x5b4c98f50842 in Py_RunMain Modules/main.c:772    #18 0x5b4c98f50a2e in pymain_main Modules/main.c:802    #19 0x5b4c98f50db3 in Py_BytesMain Modules/main.c:826    #20 0x5b4c989d4645 in main Programs/python.c:15    #21 0x7eeb96e2a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58    #22 0x7eeb96e2a28a in __libc_start_main_impl ../csu/libc-start.c:360    #23 0x5b4c989d4574 in _start (/home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-latest/targets/cpython/python+0x2dd574) (BuildId: ff3dc40ea460bd4beb2c3a72283cca525b319bf0)0x506000063ff0 is located 16 bytes inside of 56-byte region [0x506000063fe0,0x506000064018)freed by thread T0 here:    #0 0x7eeb972fc4d8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52    #1 0x5b4c98c0696d in _PyMem_RawFree Objects/obmalloc.c:91    #2 0x5b4c98c08cd9 in _PyMem_DebugRawFree Objects/obmalloc.c:2955    #3 0x5b4c98c08d1a in _PyMem_DebugFree Objects/obmalloc.c:3100    #4 0x5b4c98c30348 in PyMem_Free Objects/obmalloc.c:1070    #5 0x5b4c98bde533 in _odict_clear_nodes Objects/odictobject.c:810    #6 0x5b4c98bdff79 in OrderedDict_clear_impl Objects/odictobject.c:1227    #7 0x5b4c98bdff93 in OrderedDict_clear Objects/clinic/odictobject.c.h:353    #8 0x5b4c98bf24f3 in cfunction_vectorcall_NOARGS Objects/methodobject.c:508    #9 0x5b4c98b3fe7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169    #10 0x5b4c98b3ff72 in PyObject_Vectorcall Objects/call.c:327    #11 0x5b4c98dbe056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620    #12 0x5b4c98e01e54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121    #13 0x5b4c98e02148 in _PyEval_Vector Python/ceval.c:2001    #14 0x5b4c98b3f9b8 in _PyFunction_Vectorcall Objects/call.c:413    #15 0x5b4c98c5256b in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169    #16 0x5b4c98c52680 in vectorcall_unbound Objects/typeobject.c:3033    #17 0x5b4c98c73976 in vectorcall_method Objects/typeobject.c:3104    #18 0x5b4c98c740ee in slot_mp_subscript Objects/typeobject.c:10371    #19 0x5b4c98b0f393 in PyObject_GetItem Objects/abstract.c:163    #20 0x5b4c98be2215 in OrderedDict_copy_impl Objects/odictobject.c:1272    #21 0x5b4c98be2289 in OrderedDict_copy Objects/clinic/odictobject.c.h:377    #22 0x5b4c98b5f571 in method_vectorcall_NOARGS Objects/descrobject.c:448    #23 0x5b4c98b3fe7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169    #24 0x5b4c98b3ff72 in PyObject_Vectorcall Objects/call.c:327    #25 0x5b4c98dbe056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620    #26 0x5b4c98e01e54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121    #27 0x5b4c98e02148 in _PyEval_Vector Python/ceval.c:2001    #28 0x5b4c98e023f8 in PyEval_EvalCode Python/ceval.c:884    #29 0x5b4c98ef9507 in run_eval_code_obj Python/pythonrun.c:1365previously allocated by thread T0 here:    #0 0x7eeb972fd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69    #1 0x5b4c98c07284 in _PyMem_RawMalloc Objects/obmalloc.c:63    #2 0x5b4c98c06655 in _PyMem_DebugRawAlloc Objects/obmalloc.c:2887    #3 0x5b4c98c066bd in _PyMem_DebugRawMalloc Objects/obmalloc.c:2920    #4 0x5b4c98c07f3b in _PyMem_DebugMalloc Objects/obmalloc.c:3085    #5 0x5b4c98c30204 in PyMem_Malloc Objects/obmalloc.c:1041    #6 0x5b4c98bdf3c6 in _odict_add_new_node Objects/odictobject.c:705    #7 0x5b4c98bdfef3 in _PyODict_SetItem_KnownHash_LockHeld Objects/odictobject.c:1628    #8 0x5b4c98bdff4e in PyODict_SetItem_LockHeld Objects/odictobject.c:1648    #9 0x5b4c98be2298 in PyODict_SetItem Objects/odictobject.c:1656    #10 0x5b4c98be2321 in odict_mp_ass_sub Objects/odictobject.c:879    #11 0x5b4c98b0fbe7 in PyObject_SetItem Objects/abstract.c:237    #12 0x5b4c98bddb32 in mutablemapping_add_pairs Objects/odictobject.c:2253    #13 0x5b4c98bddfd3 in mutablemapping_update_arg Objects/odictobject.c:2330    #14 0x5b4c98bde17d in mutablemapping_update Objects/odictobject.c:2351    #15 0x5b4c98bde3ac in odict_init Objects/odictobject.c:1557    #16 0x5b4c98c663c0 in type_call Objects/typeobject.c:2460    #17 0x5b4c98b3fc71 in _PyObject_MakeTpCall Objects/call.c:242    #18 0x5b4c98b3ff19 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:167    #19 0x5b4c98b3ff72 in PyObject_Vectorcall Objects/call.c:327    #20 0x5b4c98dbe056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620    #21 0x5b4c98e01e54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121    #22 0x5b4c98e02148 in _PyEval_Vector Python/ceval.c:2001    #23 0x5b4c98e023f8 in PyEval_EvalCode Python/ceval.c:884    #24 0x5b4c98ef9507 in run_eval_code_obj Python/pythonrun.c:1365    #25 0x5b4c98ef9723 in run_mod Python/pythonrun.c:1459    #26 0x5b4c98efa57a in pyrun_file Python/pythonrun.c:1293    #27 0x5b4c98efd220 in _PyRun_SimpleFileObject Python/pythonrun.c:521    #28 0x5b4c98efd4f6 in _PyRun_AnyFileObject Python/pythonrun.c:81    #29 0x5b4c98f4e74d in pymain_run_file_obj Modules/main.c:410SUMMARY: AddressSanitizer: heap-use-after-free Objects/odictobject.c:1276 in OrderedDict_copy_implShadow bytes around the buggy address:  0x506000063d00: 00 00 00 fa fa fa fa fa fd fd fd fd fd fd fd fd  0x506000063d80: fa fa fa fa fd fd fd fd fd fd fd fd fa fa fa fa  0x506000063e00: fd fd fd fd fd fd fd fa fa fa fa fa 00 00 00 00  0x506000063e80: 00 00 00 00 fa fa fa fa fd fd fd fd fd fd fd fd  0x506000063f00: fa fa fa fa 00 00 00 00 00 00 00 fa fa fa fa fa=>0x506000063f80: fd fd fd fd fd fd fd fa fa fa fa fa fd fd[fd]fd  0x506000064000: fd fd fd fa fa fa fa fa fd fd fd fd fd fd fd fa  0x506000064080: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa  0x506000064100: fd fd fd fd fd fd fd fa fa fa fa fa fa fa fa fa  0x506000064180: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa  0x506000064200: 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==1546618==ABORTING

Metadata

Metadata

Assignees

No one assigned

    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-2025 Movatter.jp