]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-142594: fix by property calls io.TextIOWrapper.detach (GH-142706) (GH-142755)
authorCody Maloney <cmaloney@users.noreply.github.com>
Tue, 16 Dec 2025 09:55:25 +0000 (01:55 -0800)
committerGitHub <noreply@github.com>
Tue, 16 Dec 2025 09:55:25 +0000 (10:55 +0100)
(cherry picked from commit 1d3854a19a376c1fc7f71e96c620f6bc2de8cd74)

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
Co-authored-by: yihong <zouzou0208@gmail.com>
Lib/test/test_io.py
Misc/NEWS.d/next/Library/2025-12-14-18-30-48.gh-issue-142594.belDmD.rst [new file with mode: 0644]
Modules/_io/textio.c

index 6514af8b1253c344447de3a006568bee3de0caf9..57b42fbb65fe107b1573a2a6e0848de942ff8367 100644 (file)
@@ -4194,6 +4194,22 @@ class CTextIOWrapperTest(TextIOWrapperTest):
         self.assertEqual([b"abcdef", b"middle", b"g"*chunk_size],
                          buf._write_stack)
 
+    def test_issue142594(self):
+        wrapper = None
+        detached = False
+        class ReentrantRawIO(self.RawIOBase):
+            @property
+            def closed(self):
+                nonlocal detached
+                if wrapper is not None and not detached:
+                    detached = True
+                    wrapper.detach()
+                return False
+
+        raw = ReentrantRawIO()
+        wrapper = self.TextIOWrapper(raw)
+        wrapper.close()  # should not crash
+
 
 class PyTextIOWrapperTest(TextIOWrapperTest):
     io = pyio
diff --git a/Misc/NEWS.d/next/Library/2025-12-14-18-30-48.gh-issue-142594.belDmD.rst b/Misc/NEWS.d/next/Library/2025-12-14-18-30-48.gh-issue-142594.belDmD.rst
new file mode 100644 (file)
index 0000000..ee6a958
--- /dev/null
@@ -0,0 +1,2 @@
+Fix crash in ``TextIOWrapper.close()`` when the underlying buffer's
+``closed`` property calls :meth:`~io.TextIOBase.detach`.
index a136987fb52a4ae6c5bdda597322d1cea024b222..9945febea808289a705e32bb7daeecf9e30b46c8 100644 (file)
@@ -3149,6 +3149,9 @@ _io_TextIOWrapper_close_impl(textio *self)
     if (r > 0) {
         Py_RETURN_NONE; /* stream already closed */
     }
+    if (self->detached) {
+        Py_RETURN_NONE; /* gh-142594 null pointer issue */
+    }
     else {
         PyObject *exc = NULL;
         if (self->finalizing) {