gh-140650: Fix write(), flush() and close() methods of io.BufferedWriter (GH-140653)

They could raise SystemError or crash when getting the "closed" attribute
or converting it to boolean raises an exception.
This commit is contained in:
Sachin Shah 2025-11-05 14:15:27 -05:00 committed by GitHub
parent 3cb1ab0e5d
commit 1d25b751c5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 43 additions and 6 deletions

View file

@ -362,16 +362,24 @@ _enter_buffered_busy(buffered *self)
}
#define IS_CLOSED(self) \
(!self->buffer || \
(!self->buffer ? 1 : \
(self->fast_closed_checks \
? _PyFileIO_closed(self->raw) \
: buffered_closed(self)))
#define CHECK_CLOSED(self, error_msg) \
if (IS_CLOSED(self) && (Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t) == 0)) { \
PyErr_SetString(PyExc_ValueError, error_msg); \
return NULL; \
} \
do { \
int _closed = IS_CLOSED(self); \
if (_closed < 0) { \
return NULL; \
} \
if (_closed && \
(Py_SAFE_DOWNCAST(READAHEAD(self), Py_off_t, Py_ssize_t) == 0)) \
{ \
PyErr_SetString(PyExc_ValueError, error_msg); \
return NULL; \
} \
} while (0);
#define VALID_READ_BUFFER(self) \
(self->readable && self->read_end != -1)
@ -2079,6 +2087,7 @@ _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
PyObject *res = NULL;
Py_ssize_t written, avail, remaining;
Py_off_t offset;
int r;
CHECK_INITIALIZED(self)
@ -2087,7 +2096,11 @@ _io_BufferedWriter_write_impl(buffered *self, Py_buffer *buffer)
/* Issue #31976: Check for closed file after acquiring the lock. Another
thread could be holding the lock while closing the file. */
if (IS_CLOSED(self)) {
r = IS_CLOSED(self);
if (r < 0) {
goto error;
}
if (r > 0) {
PyErr_SetString(PyExc_ValueError, "write to closed file");
goto error;
}