Skip to content

gh-146427: Fix use-after-free when clearing interpreter's queue items#146428

Open
aisk wants to merge 3 commits intopython:mainfrom
aisk:interp-queue-uaf
Open

gh-146427: Fix use-after-free when clearing interpreter's queue items#146428
aisk wants to merge 3 commits intopython:mainfrom
aisk:interp-queue-uaf

Conversation

@aisk
Copy link
Member

@aisk aisk commented Mar 25, 2026

Test code:

from concurrent import interpreters
from concurrent.interpreters import _queues as queues

q = queues.create()
q.put(1)

interp = interpreters.create()
interp.exec(f"from concurrent.interpreters import _queues as queues; queues.Queue({q.id}).put(2, unbounditems=queues.UNBOUND_REMOVE)")

# del interp
interp.close()
q.put(3)

Run with ASan before this change:

./python.exe /tmp/test_queue_uaf.py
python.exe(30924,0x7ff855eaedc0) malloc: nano zone abandoned due to inability to reserve vm space.
=================================================================
==30924==ERROR: AddressSanitizer: heap-use-after-free on address 0x603000014758 at pc 0x0002d78f050f bp 0x7ff7b18a0b90 sp 0x7ff7b18a0b88
WRITE of size 8 at 0x603000014758 thread T0
    #0 0x2d78f050e in _interpqueues_put _interpqueuesmodule.c.h:265
    #1 0x10eb6d600 in _Py_BuiltinCallFastWithKeywords_StackRefSteal ceval.c:859
    #2 0x10eb75727 in _PyEval_EvalFrameDefault generated_cases.c.h:2444
    #3 0x10eb6ab2e in PyEval_EvalCode ceval.c:686
    #4 0x10ed09431 in run_mod pythonrun.c:1472
    #5 0x10ed02915 in _PyRun_SimpleFileObject pythonrun.c:518
    #6 0x10ed01d12 in _PyRun_AnyFileObject pythonrun.c:81
    #7 0x10ed7d9d9 in Py_RunMain main.c:795
    #8 0x10ed7f166 in pymain_main main.c:825
    #9 0x10ed7f470 in Py_BytesMain main.c:849
    #10 0x7ff81410352f in start+0xbef (dyld:x86_64+0xfffffffffffe652f)

0x603000014758 is located 24 bytes inside of 32-byte region [0x603000014740,0x603000014760)
freed by thread T0 here:
    #0 0x10fc07956 in free+0xa6 (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0xdd956)
    #1 0x2d78f486a in clear_interpreter _interpqueuesmodule.c:1470
    #2 0x10ed9975e in _PyAtExit_Fini atexitmodule.c:98
    #3 0x10ecf9aa3 in interpreter_clear pystate.c:871
    #4 0x10ecee073 in finalize_interp_clear pylifecycle.c:2026
    #5 0x10eceabec in Py_EndInterpreter pylifecycle.c:2707
    #6 0x10ec150bb in _PyXI_EndInterpreter crossinterp.c:3298
    #7 0x2d76e8a0f in _interpreters_destroy _interpretersmodule.c.h:162
    #8 0x10e784599 in PyObject_Vectorcall call.c:327
    #9 0x10eb6c631 in _Py_VectorCallInstrumentation_StackRefSteal ceval.c:775
    #10 0x10eb8b3e9 in _PyEval_EvalFrameDefault generated_cases.c.h:3222
    #11 0x10eb6ab2e in PyEval_EvalCode ceval.c:686
    #12 0x10ed09431 in run_mod pythonrun.c:1472
    #13 0x10ed02915 in _PyRun_SimpleFileObject pythonrun.c:518
    #14 0x10ed01d12 in _PyRun_AnyFileObject pythonrun.c:81
    #15 0x10ed7d9d9 in Py_RunMain main.c:795
    #16 0x10ed7f166 in pymain_main main.c:825
    #17 0x10ed7f470 in Py_BytesMain main.c:849
    #18 0x7ff81410352f in start+0xbef (dyld:x86_64+0xfffffffffffe652f)

previously allocated by thread T0 here:
    #0 0x10fc0780d in malloc+0x9d (libclang_rt.asan_osx_dynamic.dylib:x86_64h+0xdd80d)
    #1 0x2d78f017e in _interpqueues_put _interpqueuesmodule.c.h:265
    #2 0x10e784599 in PyObject_Vectorcall call.c:327
    #3 0x10eb6c631 in _Py_VectorCallInstrumentation_StackRefSteal ceval.c:775
    #4 0x10eb9100a in _PyEval_EvalFrameDefault generated_cases.c.h:1841
    #5 0x10eb6ab2e in PyEval_EvalCode ceval.c:686
    #6 0x2d76ec73b in _run_in_interpreter _interpretersmodule.c:690
    #7 0x2d76e9b83 in _interpreters_exec _interpretersmodule.c.h:438
    #8 0x10e784599 in PyObject_Vectorcall call.c:327
    #9 0x10eb6c631 in _Py_VectorCallInstrumentation_StackRefSteal ceval.c:775
    #10 0x10eb8b3e9 in _PyEval_EvalFrameDefault generated_cases.c.h:3222
    #11 0x10eb6ab2e in PyEval_EvalCode ceval.c:686
    #12 0x10ed09431 in run_mod pythonrun.c:1472
    #13 0x10ed02915 in _PyRun_SimpleFileObject pythonrun.c:518
    #14 0x10ed01d12 in _PyRun_AnyFileObject pythonrun.c:81
    #15 0x10ed7d9d9 in Py_RunMain main.c:795
    #16 0x10ed7f166 in pymain_main main.c:825
    #17 0x10ed7f470 in Py_BytesMain main.c:849
    #18 0x7ff81410352f in start+0xbef (dyld:x86_64+0xfffffffffffe652f)

SUMMARY: AddressSanitizer: heap-use-after-free _interpqueuesmodule.c.h:265 in _interpqueues_put
Shadow bytes around the buggy address:
  0x603000014480: fd fa fa fa fd fd fd fa fa fa fd fd fd fd fa fa
  0x603000014500: fd fd fd fa fa fa fd fd fd fa fa fa fd fd fd fa
  0x603000014580: fa fa fd fd fd fa fa fa fd fd fd fa fa fa fd fd
  0x603000014600: fd fa fa fa fd fd fd fa fa fa fd fd fd fa fa fa
  0x603000014680: fd fd fd fd fa fa fd fd fd fa fa fa fd fd fd fd
=>0x603000014700: fa fa fd fd fd fa fa fa fd fd fd[fd]fa fa 00 00
  0x603000014780: 00 00 fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x603000014800: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x603000014880: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x603000014900: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x603000014980: 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
==30924==ABORTING
fish: Job 1, './python.exe /tmp/test_queue_ua…' terminated by signal SIGABRT (Abort)

After this change, runs without crash or error.

@aisk aisk changed the title Fix use-after-free when clearing interpreter's queue items gh-146427: Fix use-after-free when clearing interpreter's queue items Mar 25, 2026
@aisk aisk added needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes labels Mar 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting review needs backport to 3.13 bugs and security fixes needs backport to 3.14 bugs and security fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant