diff options
author | Inada Naoki <songofacandy@gmail.com> | 2021-02-21 23:29:30 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-02-21 23:29:30 (GMT) |
commit | 01806d5beba3d208bb56adba6829097d803bf54f (patch) | |
tree | 3d843f7b0c03e7e8b0511a523e0f71251bc587bd /Modules/_io | |
parent | 84f7afe65c29330f3ff8e318e054b96554a2dede (diff) | |
download | cpython-01806d5beba3d208bb56adba6829097d803bf54f.zip cpython-01806d5beba3d208bb56adba6829097d803bf54f.tar.gz cpython-01806d5beba3d208bb56adba6829097d803bf54f.tar.bz2 |
bpo-43260: io: Prevent large data remains in textio buffer. (GH-24592)
When very large data remains in TextIOWrapper, flush() may fail forever.
So prevent that data larger than chunk_size is remained in TextIOWrapper internal
buffer.
Co-Authored-By: Eryk Sun
Diffstat (limited to 'Modules/_io')
-rw-r--r-- | Modules/_io/textio.c | 20 |
1 files changed, 17 insertions, 3 deletions
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c index f08d14e..03001ec 100644 --- a/Modules/_io/textio.c +++ b/Modules/_io/textio.c @@ -1585,6 +1585,8 @@ _textiowrapper_writeflush(textio *self) ret = PyObject_CallMethodOneArg(self->buffer, _PyIO_str_write, b); } while (ret == NULL && _PyIO_trap_eintr()); Py_DECREF(b); + // NOTE: We cleared buffer but we don't know how many bytes are actually written + // when an error occurred. if (ret == NULL) return -1; Py_DECREF(ret); @@ -1642,7 +1644,10 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text) /* XXX What if we were just reading? */ if (self->encodefunc != NULL) { - if (PyUnicode_IS_ASCII(text) && is_asciicompat_encoding(self->encodefunc)) { + if (PyUnicode_IS_ASCII(text) && + // See bpo-43260 + PyUnicode_GET_LENGTH(text) <= self->chunk_size && + is_asciicompat_encoding(self->encodefunc)) { b = text; Py_INCREF(b); } @@ -1651,8 +1656,9 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text) } self->encoding_start_of_stream = 0; } - else + else { b = PyObject_CallMethodOneArg(self->encoder, _PyIO_str_encode, text); + } Py_DECREF(text); if (b == NULL) @@ -1677,6 +1683,14 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text) self->pending_bytes_count = 0; self->pending_bytes = b; } + else if (self->pending_bytes_count + bytes_len > self->chunk_size) { + // Prevent to concatenate more than chunk_size data. + if (_textiowrapper_writeflush(self) < 0) { + Py_DECREF(b); + return NULL; + } + self->pending_bytes = b; + } else if (!PyList_CheckExact(self->pending_bytes)) { PyObject *list = PyList_New(2); if (list == NULL) { @@ -1696,7 +1710,7 @@ _io_TextIOWrapper_write_impl(textio *self, PyObject *text) } self->pending_bytes_count += bytes_len; - if (self->pending_bytes_count > self->chunk_size || needflush || + if (self->pending_bytes_count >= self->chunk_size || needflush || text_needflush) { if (_textiowrapper_writeflush(self) < 0) return NULL; |