GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — Heap UAF in io.TextIOWrapper read path via reentrant detach() · Issue #157363 · python/cpython

Heap UAF in io.TextIOWrapper read path via reentrant detach() #157363

New issue
Copy link
New issue
Copy link
Open
Open
Heap UAF in io.TextIOWrapper read path via reentrant detach()#157363
Copy link
Labels
extension-modulesC modules in the Modules dirC modules in the Modules dirtopic-IOtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

Description

@djarfluka
djarfluka
opened on Sep 12, 2026
Issue body actions

Bug description:

import io

class RAW(io.RawIOBase):
    def readable(self):
        return True
    def readinto(self, b):
        tw.detach()        
        b[:3] = b"abc"
        return 3

tw = io.TextIOWrapper(io.BufferedReader(RAW()), encoding="utf-8")
tw.read()
Exception ignored while finalizing file <_io.BufferedReader>:
Traceback (most recent call last):
  File "/repro/audit4/repro/textio_detach_uaf.py", line 21, in readinto
    tw.detach()
    ~~~~~~~~~^^
RuntimeError: reentrant call inside <_io.BufferedReader>
=================================================================
==1==ERROR: AddressSanitizer: heap-use-after-free on address 0x50f000039ff0 at pc 0xaaaad92e3ca4 bp 0xffffeddd0980 sp 0xffffeddd0970
WRITE of size 8 at 0x50f000039ff0 thread T0
    #0 0xaaaad92e3ca0 in _io__Buffered_read_impl Modules/_io/bufferedio.c:1022
    #1 0xaaaad92e3ca0 in _io__Buffered_read Modules/_io/clinic/bufferedio.c.h:677
    #2 0xaaaad8869b50 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #3 0xaaaad8869b50 in PyObject_VectorcallMethod Objects/call.c:921
    #4 0xaaaad92eb514 in PyObject_CallMethodNoArgs Include/cpython/abstract.h:65
    #5 0xaaaad92eb514 in buffer_callmethod_noargs Modules/_io/textio.c:781
    #6 0xaaaad93061e8 in _io_TextIOWrapper_read_impl Modules/_io/textio.c:2083
    #7 0xaaaad93061e8 in _io_TextIOWrapper_read Modules/_io/clinic/textio.c.h:857
    #8 0xaaaad8866320 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #9 0xaaaad8866320 in PyObject_Vectorcall Objects/call.c:327
    #10 0xaaaad8eb1bc8 in _Py_VectorCallInstrumentation_StackRefSteal Python/ceval.c:768
    #11 0xaaaad85e1de8 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1906
    #12 0xaaaad8ed0b1c in _PyEval_EvalFrame Include/internal/pycore_ceval.h:122
    #13 0xaaaad8ed0b1c in _PyEval_Vector Python/ceval.c:2174
    #14 0xaaaad8ed0b1c in PyEval_EvalCode Python/ceval.c:679
    #15 0xaaaad90cfeb4 in run_mod Python/pythonrun.c:1509
    #16 0xaaaad90d0d38 in _PyRun_File Python/pythonrun.c:1332
    #17 0xaaaad90d4ffc in _PyRun_SimpleFile Python/pythonrun.c:544
    #18 0xaaaad90d8dd0 in _PyRun_AnyFile Python/pythonrun.c:92
    #19 0xaaaad91a390c in pymain_run_file_obj Modules/main.c:478
    #20 0xaaaad91a390c in pymain_run_file Modules/main.c:494
    #21 0xaaaad91a390c in pymain_run_python Modules/main.c:804
    #22 0xaaaad91a390c in Py_RunMain Modules/main.c:891
    #23 0xaaaad91a5c38 in pymain_main Modules/main.c:921
    #24 0xaaaad91a5c38 in Py_BytesMain Modules/main.c:945
    #25 0xffff9b6684c0  (/lib/aarch64-linux-gnu/libc.so.6+0x284c0) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #26 0xffff9b668594 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x28594) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #27 0xaaaad864beec in _start (/src/cpython/python+0x183beec) (BuildId: eba909a3db0adabacf151d7dc3081dda7999191a)

0x50f000039ff0 is located 128 bytes inside of 168-byte region [0x50f000039f70,0x50f00003a018)
freed by thread T0 here:
    #0 0xffff9c0061b4 in free ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:52
    #1 0xaaaad92cd8dc in buffered_dealloc Modules/_io/bufferedio.c:444
    #2 0xaaaad8a57ab0 in _Py_Dealloc Objects/object.c:3334
    #3 0xaaaad860fea0 in Py_DECREF_MORTAL Include/internal/pycore_object.h:449
    #4 0xaaaad860fea0 in PyStackRef_XCLOSE Include/internal/pycore_stackref.h:726
    #5 0xaaaad860fea0 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:11163
    #6 0xaaaad8ed1a00 in _PyEval_EvalFrame Include/internal/pycore_ceval.h:122
    #7 0xaaaad8ed1a00 in _PyEval_Vector Python/ceval.c:2174
    #8 0xaaaad8864e58 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #9 0xaaaad8864e58 in object_vacall Objects/call.c:823
    #10 0xaaaad886a2c8 in PyObject_CallMethodObjArgs Objects/call.c:960
    #11 0xaaaad92b253c in _io__RawIOBase_read_impl Modules/_io/iobase.c:936
    #12 0xaaaad92b253c in _io__RawIOBase_read Modules/_io/clinic/iobase.c.h:425
    #13 0xaaaad8865880 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #14 0xaaaad8865880 in _PyObject_CallFunctionVa Objects/call.c:552
    #15 0xaaaad8867aa0 in callmethod Objects/call.c:626
    #16 0xaaaad8867aa0 in _PyObject_CallMethod Objects/call.c:694
    #17 0xaaaad92b1cec in _io__RawIOBase_readall_impl Modules/_io/iobase.c:979
    #18 0xaaaad92b1cec in _io__RawIOBase_readall Modules/_io/clinic/iobase.c.h:446
    #19 0xaaaad92e2d88 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #20 0xaaaad92e2d88 in _PyObject_CallNoArgs Include/internal/pycore_call.h:160
    #21 0xaaaad92e2d88 in _bufferedreader_read_all Modules/_io/bufferedio.c:1717
    #22 0xaaaad92e2d88 in _io__Buffered_read_impl Modules/_io/bufferedio.c:1010
    #23 0xaaaad92e2d88 in _io__Buffered_read Modules/_io/clinic/bufferedio.c.h:677
    #24 0xaaaad8869b50 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #25 0xaaaad8869b50 in PyObject_VectorcallMethod Objects/call.c:921
    #26 0xaaaad92eb514 in PyObject_CallMethodNoArgs Include/cpython/abstract.h:65
    #27 0xaaaad92eb514 in buffer_callmethod_noargs Modules/_io/textio.c:781
    #28 0xaaaad93061e8 in _io_TextIOWrapper_read_impl Modules/_io/textio.c:2083
    #29 0xaaaad93061e8 in _io_TextIOWrapper_read Modules/_io/clinic/textio.c.h:857
    #30 0xaaaad8866320 in _PyObject_VectorcallTstate Include/internal/pycore_call.h:144
    #31 0xaaaad8866320 in PyObject_Vectorcall Objects/call.c:327
    #32 0xaaaad8eb1bc8 in _Py_VectorCallInstrumentation_StackRefSteal Python/ceval.c:768
    #33 0xaaaad85e1de8 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1906
    #34 0xaaaad8ed0b1c in _PyEval_EvalFrame Include/internal/pycore_ceval.h:122
    #35 0xaaaad8ed0b1c in _PyEval_Vector Python/ceval.c:2174
    #36 0xaaaad8ed0b1c in PyEval_EvalCode Python/ceval.c:679
    #37 0xaaaad90cfeb4 in run_mod Python/pythonrun.c:1509
    #38 0xaaaad90d0d38 in _PyRun_File Python/pythonrun.c:1332
    #39 0xaaaad90d4ffc in _PyRun_SimpleFile Python/pythonrun.c:544
    #40 0xaaaad90d8dd0 in _PyRun_AnyFile Python/pythonrun.c:92
    #41 0xaaaad91a390c in pymain_run_file_obj Modules/main.c:478
    #42 0xaaaad91a390c in pymain_run_file Modules/main.c:494
    #43 0xaaaad91a390c in pymain_run_python Modules/main.c:804
    #44 0xaaaad91a390c in Py_RunMain Modules/main.c:891
    #45 0xaaaad91a5c38 in pymain_main Modules/main.c:921
    #46 0xaaaad91a5c38 in Py_BytesMain Modules/main.c:945
    #47 0xffff9b6684c0  (/lib/aarch64-linux-gnu/libc.so.6+0x284c0) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #48 0xffff9b668594 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x28594) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #49 0xaaaad864beec in _start (/src/cpython/python+0x183beec) (BuildId: eba909a3db0adabacf151d7dc3081dda7999191a)

previously allocated by thread T0 here:
    #0 0xffff9c0076d0 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69
    #1 0xaaaad8b7077c in _PyObject_MallocWithType Include/internal/pycore_object_alloc.h:46
    #2 0xaaaad8b7077c in _PyType_AllocNoTrack Objects/typeobject.c:2498
    #3 0xaaaad8b70e00 in PyType_GenericAlloc Objects/typeobject.c:2529
    #4 0xaaaad8b76808 in type_call Objects/typeobject.c:2442
    #5 0xaaaad8864250 in _PyObject_MakeTpCall Objects/call.c:242
    #6 0xaaaad8eb1bc8 in _Py_VectorCallInstrumentation_StackRefSteal Python/ceval.c:768
    #7 0xaaaad85e1de8 in _PyEval_EvalFrameDefault Python/generated_cases.c.h:1906
    #8 0xaaaad8ed0b1c in _PyEval_EvalFrame Include/internal/pycore_ceval.h:122
    #9 0xaaaad8ed0b1c in _PyEval_Vector Python/ceval.c:2174
    #10 0xaaaad8ed0b1c in PyEval_EvalCode Python/ceval.c:679
    #11 0xaaaad90cfeb4 in run_mod Python/pythonrun.c:1509
    #12 0xaaaad90d0d38 in _PyRun_File Python/pythonrun.c:1332
    #13 0xaaaad90d4ffc in _PyRun_SimpleFile Python/pythonrun.c:544
    #14 0xaaaad90d8dd0 in _PyRun_AnyFile Python/pythonrun.c:92
    #15 0xaaaad91a390c in pymain_run_file_obj Modules/main.c:478
    #16 0xaaaad91a390c in pymain_run_file Modules/main.c:494
    #17 0xaaaad91a390c in pymain_run_python Modules/main.c:804
    #18 0xaaaad91a390c in Py_RunMain Modules/main.c:891
    #19 0xaaaad91a5c38 in pymain_main Modules/main.c:921
    #20 0xaaaad91a5c38 in Py_BytesMain Modules/main.c:945
    #21 0xffff9b6684c0  (/lib/aarch64-linux-gnu/libc.so.6+0x284c0) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #22 0xffff9b668594 in __libc_start_main (/lib/aarch64-linux-gnu/libc.so.6+0x28594) (BuildId: 27027b96e5b8c475fc327aa445bea1c71d37b4e2)
    #23 0xaaaad864beec in _start (/src/cpython/python+0x183beec) (BuildId: eba909a3db0adabacf151d7dc3081dda7999191a)

SUMMARY: AddressSanitizer: heap-use-after-free Modules/_io/bufferedio.c:1022 in _io__Buffered_read_impl
Shadow bytes around the buggy address:
  0x50f000039d00: fd fd fd fd fd fd fd fd fd fa fa fa fa fa fa fa
  0x50f000039d80: fa fa 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x50f000039e00: 00 00 00 00 00 00 00 fa fa fa fa fa fa fa fa fa
  0x50f000039e80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  0x50f000039f00: 00 00 00 00 00 fa fa fa fa fa fa fa fa fa fd fd
=>0x50f000039f80: fd fd fd fd fd fd fd fd fd fd fd fd fd fd[fd]fd
  0x50f00003a000: fd fd fd fa fa fa fa fa fa fa fa fa fd fd fd fd
  0x50f00003a080: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd
  0x50f00003a100: fd fa fa fa fa fa fa fa fa fa fd fd fd fd fd fd
  0x50f00003a180: fd fd fd fd fd fd fd fd fd fd fd fd fd fd fd fa
  0x50f00003a200: fa fa fa fa fa fa fa fa fd fd fd fd fd fd fd fd
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
==1==ABORTING

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Activity

  1. djarfluka
    added
    type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
    on Sep 12, 2026
  2. StanFromIreland
    added
    extension-modulesC modules in the Modules dirC modules in the Modules dir
    topic-free-threading
    on Sep 12, 2026
  3. ashm-dev commented on Sep 13, 2026

    @ashm-dev
    ashm-dev
    on Sep 13, 2026
    Contributor
    More actions

    My PR also captures this issue; here's the result when playing it back on it

    ❯ ./python -X dev bug.py
    Traceback (most recent call last):
      File "/home/boss/projects/oss/cpython/main/bug.py", line 12, in <module>
        tw.read()
        ~~~~~~~^^
      File "/home/boss/projects/oss/cpython/main/bug.py", line 7, in readinto
        tw.detach()
        ~~~~~~~~~^^
    ValueError: underlying buffer has been detached
    
  4. ashm-dev commented on Sep 13, 2026

    @ashm-dev
    ashm-dev
    on Sep 13, 2026
    Contributor
    More actions

    @StanFromIreland The problem has nothing to do with free-threading.

  5. StanFromIreland
    removed
    topic-free-threading
    on Sep 13, 2026
  6. djarfluka commented on Sep 13, 2026

    @djarfluka
    djarfluka
    on Sep 13, 2026
    Author
    More actions

    @ashm-dev send him 2-3 years dagestan and forget

    Reacted by Shamil
  7. StanFromIreland commented on Sep 13, 2026

    @StanFromIreland
    StanFromIreland
    on Sep 13, 2026
    Member
    More actions

    @djarfluka Please remember that all interactions on Python Software Foundation-supported infrastructure are covered by the PSF Code of Conduct. See the devguide for more information.

  8. cmaloney
    added
    topic-IO
    on Sep 26, 2026
  9. kevinprimeraquecreo-stack
    added this to Project_VKon Oct 18, 2026
  10. github-project-automation
    moved this to Todo in Project_VKon Oct 18, 2026
  11. kevinprimeraquecreo-stack
    added this to Project_VKon Oct 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    extension-modulesC modules in the Modules dirC modules in the Modules dirtopic-IOtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.