Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
42caa08
gh-143008: Safer TextIOWrapper underlying stream access
cmaloney Mar 15, 2026
551c3eb
fixup: Refer to existing helpers
cmaloney Mar 15, 2026
4f455f4
fixup: More precise recursion errorcatching
cmaloney Mar 17, 2026
ec39a61
fixup: Formatting fixes, simplify test
cmaloney Mar 17, 2026
98bc865
fixup: correct commment
cmaloney Mar 17, 2026
c52559b
PEP 7 fixes; simplify some comments
cmaloney Mar 30, 2026
210b21b
Merge branch 'main' into textio_nullbuffer
cmaloney Mar 30, 2026
150fcee
Improve PEP-7
cmaloney Apr 20, 2026
d7f14fc
PEP-7: Move to shorter function names, reformat arg lists
cmaloney Apr 21, 2026
df212a5
Improve NEWS grammer
cmaloney Apr 21, 2026
d1a1a98
Simplify comment
cmaloney Apr 21, 2026
009cf12
Fix comment referring to function name
cmaloney Apr 21, 2026
afe79c7
Apply suggestions from code review
cmaloney Jun 5, 2026
452168c
Assert self->buffer is locked, fix __init__ race
cmaloney Jun 5, 2026
d7b146e
Adjust closed_get_impl
cmaloney Jun 5, 2026
593b0ea
Add back in locked assterion, match surrounding comment style
cmaloney Jun 5, 2026
e5c014a
Move null checks up a line
cmaloney Jun 5, 2026
eb23eaa
Merge remote-tracking branch 'upstream/main' into textio_nullbuffer
cmaloney Jun 5, 2026
2581e6c
Fix clinic merge
cmaloney Jun 5, 2026
feafb90
Fix blurb
cmaloney Jun 5, 2026
c0bdd84
Apply suggestions from code review
cmaloney Jun 9, 2026
d7bf513
Remove wrapper_ref, use simpler classes, wrapper local only
cmaloney Jun 9, 2026
a24957d
Separate attribute and submodule imports
cmaloney Jun 9, 2026
c2cb455
Fix NULL with no exception after flush in detach
cmaloney Jun 9, 2026
cbcd21a
remove recursion. Add make_text helper and DetachOnce
cmaloney Jun 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 50 additions & 0 deletions Lib/test/test_io/test_textio.py
Original file line number Diff line number Diff line change
Expand Up @@ -1560,6 +1560,56 @@ def closed(self):
wrapper = self.TextIOWrapper(raw)
wrapper.close() # should not crash

def test_reentrant_detach_during_flush(self):
# gh-143008: Reentrant detach() during flush should not crash.
Comment thread
cmaloney marked this conversation as resolved.

class DetachOnce(self.BufferedRandom):
wrapper = None

def detach_once(self):
original = self.wrapper
self.wrapper = None
if original is not None:
original.detach()
original.flush()

class DetachOnFlush(DetachOnce):
def flush(self):
self.detach_once()

class DetachOnWrite(DetachOnce):
def write(self, b):
self.detach_once()
return len(b)

# Separate reference for after detach_once.
wrapper = None

def make_text(buffer):
nonlocal wrapper
buffer.wrapper = self.TextIOWrapper(buffer, encoding='utf-8')
wrapper = buffer.wrapper

# Many calls could result in the same null self->buffer crash.
tests = [
('truncate', lambda: wrapper.truncate(0)),
('close', lambda: wrapper.close()),
('detach', lambda: wrapper.detach()),
('seek', lambda: wrapper.seek(0)),
('tell', lambda: wrapper.tell()),
('reconfigure', lambda: wrapper.reconfigure(line_buffering=True)),
]
for name, method in tests:
with self.subTest(name):
make_text(DetachOnFlush(self.MockRawIO()))
self.assertRaisesRegex(ValueError, "detached", method)

# Should not crash.
with self.subTest('read via writeflush'):
make_text(DetachOnWrite(self.MockRawIO()))
wrapper.write('x')
self.assertRaisesRegex(ValueError, "detached", wrapper.read)


class PyTextIOWrapperTest(TextIOWrapperTest, PyTestCase):
shutdown_error = "LookupError: unknown encoding: ascii"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix crash in :class:`io.TextIOWrapper` when reentrant
:meth:`io.TextIOBase.detach` is called reentrantly from the underlying buffer.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix race conditions when re-initializing a :class:`io.TextIOWrapper` object.
4 changes: 3 additions & 1 deletion Modules/_io/clinic/textio.c.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading