Skip to content

_io.BufferedReader.read1() leaves object in reentrant state after MemoryError #143689

@hyongtao-code

Description

@hyongtao-code

Bug report

Bug description:

BufferedReader.read1() can leave the object in a broken (reentrant) state after an allocation failure.

Reproducer

import io
import sys

def repro():
    br = io.BufferedReader(io.BytesIO(b"hello world"), buffer_size=8)

    huge = 10**18
    try:
        br.read1(huge)
    except Exception as e:
        print("first call exception:", type(e).__name__, e)

    try:
        x = br.read1(1)
        print("second call ok:", x)
    except Exception as e:
        print("second call exception:", type(e).__name__, e)

    br2 = io.BufferedReader(io.BytesIO(b"hello world"), buffer_size=8)
    print("fresh object read1:", br2.read1(1))

if __name__ == "__main__":
    print("python:", sys.version)
    repro()

Wrong behavior

D:\MyCode\cpython\PCbuild\amd64>python_d.exe py_iobuffer.py
python: 3.15.0a3+ (heads/main-dirty:78e868fa28, Jan 11 2026, 12:40:52) [MSC v.1950 64 bit (AMD64)]
first call exception: MemoryError
second call exception: RuntimeError reentrant call inside <_io.BufferedReader>
fresh object read1: b'h'
Exception ignored while finalizing file <_io.BufferedReader>:
Traceback (most recent call last):
  File "D:\MyCode\cpython\PCbuild\amd64\py_iobuffer.py", line 24, in <module>
    repro()
    ~~~~~^^
RuntimeError: reentrant call inside <_io.BufferedReader>

CPython versions tested on:

CPython main branch

Operating systems tested on:

Windows

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions