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?
hash(memoryview) (read-only, byte format) callsPyObject_Hash(view->obj) insidememory_hash. If the exporter’s__hash__ mutates or frees its buffer (e.g., by releasing thememoryview and then resizing/clearing the underlying array),memory_hash continues and hashes from a staleview->buf, leading to a heap use-after-free.
Note that this is similar to#142665, while with a different reentrant place.
Proof of Concept:
importarrayclassEvil(array.array):def__hash__(self):globalmvmv.release()# drop the export so the buffer can be freedself.clear()# free the backing storagereturn123# hash() still succeedsdata=Evil('B',b'A'*4096)mv=memoryview(data).toreadonly()# must be read-only for hash()print(hash(mv))
Affected Versions:
Details
| Python Version | Status | Exit Code |
|---|---|---|
Python 3.9.24+ (heads/3.9:9c4638d, Oct 17 2025, 11:19:30) | Exception | 1 |
Python 3.10.19+ (heads/3.10:0142619, Oct 17 2025, 11:20:05) [GCC 13.3.0] | Exception | 1 |
Python 3.11.14+ (heads/3.11:88f3f5b, Oct 17 2025, 11:20:44) [GCC 13.3.0] | Exception | 1 |
Python 3.12.12+ (heads/3.12:8cb2092, Oct 17 2025, 11:21:35) [GCC 13.3.0] | Exception | 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] | ASAN | 1 |
Related Code Snippet
Details
staticPy_hash_tmemory_hash(PyObject*_self){PyMemoryViewObject*self= (PyMemoryViewObject*)_self;if (self->hash==-1) {Py_buffer*view=&self->view;char*mem=view->buf;Py_ssize_tret;charfmt;CHECK_RELEASED_INT(self);if (!view->readonly) {PyErr_SetString(PyExc_ValueError,"cannot hash writable memoryview object");return-1; }ret=get_native_fmtchar(&fmt,view->format);if (ret<0|| !IS_BYTE_FORMAT(fmt)) {PyErr_SetString(PyExc_ValueError,"memoryview: hashing is restricted to formats 'B', 'b' or 'c'");return-1; }// Bug: PyObject_Hash clear the array elements to free view->bufif (view->obj!=NULL&&PyObject_Hash(view->obj)==-1) {/* Keep the original error message */return-1; }if (!MV_C_CONTIGUOUS(self->flags)) {mem=PyMem_Malloc(view->len);if (mem==NULL) {PyErr_NoMemory();return-1; }if (buffer_to_contiguous(mem,view,'C')<0) {PyMem_Free(mem);return-1; } }/* Can't fail */// Trigger: mem is now pointing to a freed bufferself->hash=Py_HashBuffer(mem,view->len);if (mem!=view->buf)PyMem_Free(mem); }returnself->hash;}
Sanitizer Output:
Details
===================================================================1543499==ERROR: AddressSanitizer: heap-use-after-free on address 0x52100001f510 at pc 0x58bc9b186b08 bp 0x7fff4881d0a0 sp 0x7fff4881d090READ of size 8 at 0x52100001f510 thread T0 #0 0x58bc9b186b07 in memcpy /usr/include/x86_64-linux-gnu/bits/string_fortified.h:29 #1 0x58bc9b186b07 in siphash13 Python/pyhash.c:385 #2 0x58bc9b186f3c in pysiphash Python/pyhash.c:481 #3 0x58bc9b18728d in Py_HashBuffer Python/pyhash.c:190 #4 0x58bc9ae96655 in memory_hash Objects/memoryobject.c:3246 #5 0x58bc9aea63d6 in PyObject_Hash Objects/object.c:1157 #6 0x58bc9b049fcc in builtin_hash Python/bltinmodule.c:1772 #7 0x58bc9ae9c3fe in cfunction_vectorcall_O Objects/methodobject.c:536 #8 0x58bc9ade9e7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169 #9 0x58bc9ade9f72 in PyObject_Vectorcall Objects/call.c:327 #10 0x58bc9b068056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620 #11 0x58bc9b0abe54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121 #12 0x58bc9b0ac148 in _PyEval_Vector Python/ceval.c:2001 #13 0x58bc9b0ac3f8 in PyEval_EvalCode Python/ceval.c:884 #14 0x58bc9b1a3507 in run_eval_code_obj Python/pythonrun.c:1365 #15 0x58bc9b1a3723 in run_mod Python/pythonrun.c:1459 #16 0x58bc9b1a457a in pyrun_file Python/pythonrun.c:1293 #17 0x58bc9b1a7220 in _PyRun_SimpleFileObject Python/pythonrun.c:521 #18 0x58bc9b1a74f6 in _PyRun_AnyFileObject Python/pythonrun.c:81 #19 0x58bc9b1f874d in pymain_run_file_obj Modules/main.c:410 #20 0x58bc9b1f89b4 in pymain_run_file Modules/main.c:429 #21 0x58bc9b1fa1b2 in pymain_run_python Modules/main.c:691 #22 0x58bc9b1fa842 in Py_RunMain Modules/main.c:772 #23 0x58bc9b1faa2e in pymain_main Modules/main.c:802 #24 0x58bc9b1fadb3 in Py_BytesMain Modules/main.c:826 #25 0x58bc9ac7e645 in main Programs/python.c:15 #26 0x74bb6882a1c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #27 0x74bb6882a28a in __libc_start_main_impl ../csu/libc-start.c:360 #28 0x58bc9ac7e574 in _start (/home/jackfromeast/Desktop/entropy/tasks/grammar-afl++-latest/targets/cpython/python+0x2dd574) (BuildId: ff3dc40ea460bd4beb2c3a72283cca525b319bf0)0x52100001f510 is located 16 bytes inside of 4379-byte region [0x52100001f500,0x52100002061b)freed by thread T0 here: #0 0x74bb68cfc4d8 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52 #1 0x58bc9aeb096d in _PyMem_RawFree Objects/obmalloc.c:91 #2 0x58bc9aeb2cd9 in _PyMem_DebugRawFree Objects/obmalloc.c:2955 #3 0x58bc9aeb2d1a in _PyMem_DebugFree Objects/obmalloc.c:3100 #4 0x58bc9aeda348 in PyMem_Free Objects/obmalloc.c:1070 #5 0x74bb67da2c97 in array_resize Modules/arraymodule.c:159 #6 0x74bb67da337e in array_array_clear_impl Modules/arraymodule.c:894 #7 0x74bb67da33a0 in array_array_clear Modules/clinic/arraymodule.c.h:26 #8 0x58bc9ae09571 in method_vectorcall_NOARGS Objects/descrobject.c:448 #9 0x58bc9ade9e7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169 #10 0x58bc9ade9f72 in PyObject_Vectorcall Objects/call.c:327 #11 0x58bc9b068056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620 #12 0x58bc9b0abe54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121 #13 0x58bc9b0ac148 in _PyEval_Vector Python/ceval.c:2001 #14 0x58bc9ade99b8 in _PyFunction_Vectorcall Objects/call.c:413 #15 0x58bc9ade9e7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169 #16 0x58bc9adea03f in PyObject_CallOneArg Objects/call.c:395 #17 0x58bc9aefc648 in call_unbound_noarg Objects/typeobject.c:3040 #18 0x58bc9af17fa0 in maybe_call_special_no_args Objects/typeobject.c:3153 #19 0x58bc9af185e4 in slot_tp_hash Objects/typeobject.c:10564 #20 0x58bc9aea63d6 in PyObject_Hash Objects/object.c:1157 #21 0x58bc9ae965cc in memory_hash Objects/memoryobject.c:3228 #22 0x58bc9aea63d6 in PyObject_Hash Objects/object.c:1157 #23 0x58bc9b049fcc in builtin_hash Python/bltinmodule.c:1772 #24 0x58bc9ae9c3fe in cfunction_vectorcall_O Objects/methodobject.c:536 #25 0x58bc9ade9e7f in _PyObject_VectorcallTstate Include/internal/pycore_call.h:169 #26 0x58bc9ade9f72 in PyObject_Vectorcall Objects/call.c:327 #27 0x58bc9b068056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620 #28 0x58bc9b0abe54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121 #29 0x58bc9b0ac148 in _PyEval_Vector Python/ceval.c:2001previously allocated by thread T0 here: #0 0x74bb68cfd9c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69 #1 0x58bc9aeb1284 in _PyMem_RawMalloc Objects/obmalloc.c:63 #2 0x58bc9aeb0655 in _PyMem_DebugRawAlloc Objects/obmalloc.c:2887 #3 0x58bc9aeb364f in _PyMem_DebugRawRealloc Objects/obmalloc.c:2963 #4 0x58bc9aeb3823 in _PyMem_DebugRealloc Objects/obmalloc.c:3108 #5 0x58bc9aeda2e7 in PyMem_Realloc Objects/obmalloc.c:1063 #6 0x74bb67da2b78 in array_resize Modules/arraymodule.c:183 #7 0x74bb67da59dd in frombytes Modules/arraymodule.c:1721 #8 0x74bb67da5a63 in array_array_frombytes_impl Modules/arraymodule.c:1746 #9 0x74bb67da5b97 in array_array_frombytes Modules/clinic/arraymodule.c.h:539 #10 0x74bb67da657d in array_new Modules/arraymodule.c:2812 #11 0x58bc9af10346 in type_call Objects/typeobject.c:2448 #12 0x58bc9ade9c71 in _PyObject_MakeTpCall Objects/call.c:242 #13 0x58bc9ade9f19 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:167 #14 0x58bc9ade9f72 in PyObject_Vectorcall Objects/call.c:327 #15 0x58bc9b068056 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1620 #16 0x58bc9b0abe54 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:121 #17 0x58bc9b0ac148 in _PyEval_Vector Python/ceval.c:2001 #18 0x58bc9b0ac3f8 in PyEval_EvalCode Python/ceval.c:884 #19 0x58bc9b1a3507 in run_eval_code_obj Python/pythonrun.c:1365 #20 0x58bc9b1a3723 in run_mod Python/pythonrun.c:1459 #21 0x58bc9b1a457a in pyrun_file Python/pythonrun.c:1293 #22 0x58bc9b1a7220 in _PyRun_SimpleFileObject Python/pythonrun.c:521 #23 0x58bc9b1a74f6 in _PyRun_AnyFileObject Python/pythonrun.c:81 #24 0x58bc9b1f874d in pymain_run_file_obj Modules/main.c:410 #25 0x58bc9b1f89b4 in pymain_run_file Modules/main.c:429 #26 0x58bc9b1fa1b2 in pymain_run_python Modules/main.c:691 #27 0x58bc9b1fa842 in Py_RunMain Modules/main.c:772 #28 0x58bc9b1faa2e in pymain_main Modules/main.c:802 #29 0x58bc9b1fadb3 in Py_BytesMain Modules/main.c:826SUMMARY: AddressSanitizer: heap-use-after-free /usr/include/x86_64-linux-gnu/bits/string_fortified.h:29 in memcpyShadow bytes around the buggy address: 0x52100001f280: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x52100001f300: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x52100001f380: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x52100001f400: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa 0x52100001f480: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa=>0x52100001f500: fd fd[fd]fd fd fd fd fd fd fd fd fd fd fd fd fd 0x52100001f580: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x52100001f600: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x52100001f680: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x52100001f700: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd 0x52100001f780: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fdShadow 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==1543499==ABORTINLinked PRs
- gh-142664: fix UAF in
memoryview.__hash__via re-entrant data's__hash__#143217 - [3.14] gh-142664: fix UAF in
memoryview.__hash__via re-entrant data's__hash__(GH-143217) #143221 - [3.13] gh-142664: fix UAF in
memoryview.__hash__via re-entrant data's__hash__(GH-143217) #143222 - gh-142664: fix
PyObject_Hashinvokation post GH-143217 #143223 - [3.14] gh-142664: fix
PyObject_Hashinvokation post GH-143217 (GH-143223) #143224 - [3.13] gh-142664: fix
PyObject_Hashinvokation post GH-143217 (GH-143223) #143225