summaryrefslogtreecommitdiffstats
path: root/Modules/_io
diff options
context:
space:
mode:
authorInada Naoki <songofacandy@gmail.com>2021-02-22 01:32:55 (GMT)
committerGitHub <noreply@github.com>2021-02-22 01:32:55 (GMT)
commitd51436f95bf5978f82d917e53e9a456fdaa83a9d (patch)
tree079850b8608542c44004cb085438270a6d77b997 /Modules/_io
parent44fe32061d60f4bd9c4fa48c24e3e4ba26033dba (diff)
downloadcpython-d51436f95bf5978f82d917e53e9a456fdaa83a9d.zip
cpython-d51436f95bf5978f82d917e53e9a456fdaa83a9d.tar.gz
cpython-d51436f95bf5978f82d917e53e9a456fdaa83a9d.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 (cherry picked from commit 01806d5)
Diffstat (limited to 'Modules/_io')
-rw-r--r--Modules/_io/textio.c20
1 files changed, 17 insertions, 3 deletions
diff --git a/Modules/_io/textio.c b/Modules/_io/textio.c
index f2c72eb..966c532 100644
--- a/Modules/_io/textio.c
+++ b/Modules/_io/textio.c
@@ -1602,6 +1602,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);
@@ -1659,7 +1661,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);
}
@@ -1668,8 +1673,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)
@@ -1694,6 +1700,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) {
@@ -1713,7 +1727,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;