Commit eab421bf authored by Serhiy Storchaka's avatar Serhiy Storchaka Committed by GitHub

[2.7] bpo-25862: Fix several bugs in the _io module. (GH-8026) (GH-8033)

They can be exposed when some C API calls fail due to lack of
memory.

* Failed Py_BuildValue() could cause an assertion error in the
  following TextIOWrapper.tell().
* initvalue could leak in StringIO.__getstate__() after failed
  PyDict_Copy().
(cherry picked from commit fdb5a50e)
parent 8687bd86
...@@ -693,8 +693,10 @@ stringio_getstate(stringio *self) ...@@ -693,8 +693,10 @@ stringio_getstate(stringio *self)
} }
else { else {
dict = PyDict_Copy(self->dict); dict = PyDict_Copy(self->dict);
if (dict == NULL) if (dict == NULL) {
Py_DECREF(initvalue);
return NULL; return NULL;
}
} }
state = Py_BuildValue("(OOnN)", initvalue, state = Py_BuildValue("(OOnN)", initvalue,
......
...@@ -1466,6 +1466,7 @@ textiowrapper_read_chunk(textio *self) ...@@ -1466,6 +1466,7 @@ textiowrapper_read_chunk(textio *self)
/* At the snapshot point, len(dec_buffer) bytes before the read, the /* At the snapshot point, len(dec_buffer) bytes before the read, the
* next input to be decoded is dec_buffer + input_chunk. * next input to be decoded is dec_buffer + input_chunk.
*/ */
PyObject *snapshot;
PyObject *next_input = PyNumber_Add(dec_buffer, input_chunk); PyObject *next_input = PyNumber_Add(dec_buffer, input_chunk);
if (next_input == NULL) if (next_input == NULL)
goto fail; goto fail;
...@@ -1477,8 +1478,13 @@ textiowrapper_read_chunk(textio *self) ...@@ -1477,8 +1478,13 @@ textiowrapper_read_chunk(textio *self)
Py_DECREF(next_input); Py_DECREF(next_input);
goto fail; goto fail;
} }
snapshot = Py_BuildValue("NN", dec_flags, next_input);
if (snapshot == NULL) {
dec_flags = NULL;
goto fail;
}
Py_XSETREF(self->snapshot, snapshot);
Py_DECREF(dec_buffer); Py_DECREF(dec_buffer);
Py_XSETREF(self->snapshot, Py_BuildValue("NN", dec_flags, next_input));
} }
Py_DECREF(input_chunk); Py_DECREF(input_chunk);
...@@ -2013,6 +2019,7 @@ textiowrapper_seek(textio *self, PyObject *args) ...@@ -2013,6 +2019,7 @@ textiowrapper_seek(textio *self, PyObject *args)
int whence = 0; int whence = 0;
PyObject *res; PyObject *res;
int cmp; int cmp;
PyObject *snapshot;
CHECK_ATTACHED(self); CHECK_ATTACHED(self);
...@@ -2149,11 +2156,11 @@ textiowrapper_seek(textio *self, PyObject *args) ...@@ -2149,11 +2156,11 @@ textiowrapper_seek(textio *self, PyObject *args)
goto fail; goto fail;
} }
self->snapshot = Py_BuildValue("iN", cookie.dec_flags, input_chunk); snapshot = Py_BuildValue("iN", cookie.dec_flags, input_chunk);
if (self->snapshot == NULL) { if (snapshot == NULL) {
Py_DECREF(input_chunk);
goto fail; goto fail;
} }
Py_XSETREF(self->snapshot, snapshot);
decoded = PyObject_CallMethod(self->decoder, "decode", decoded = PyObject_CallMethod(self->decoder, "decode",
"Oi", input_chunk, (int)cookie.need_eof); "Oi", input_chunk, (int)cookie.need_eof);
...@@ -2171,9 +2178,10 @@ textiowrapper_seek(textio *self, PyObject *args) ...@@ -2171,9 +2178,10 @@ textiowrapper_seek(textio *self, PyObject *args)
self->decoded_chars_used = cookie.chars_to_skip; self->decoded_chars_used = cookie.chars_to_skip;
} }
else { else {
self->snapshot = Py_BuildValue("is", cookie.dec_flags, ""); snapshot = Py_BuildValue("is", cookie.dec_flags, "");
if (self->snapshot == NULL) if (snapshot == NULL)
goto fail; goto fail;
Py_XSETREF(self->snapshot, snapshot);
} }
/* Finally, reset the encoder (merely useful for proper BOM handling) */ /* Finally, reset the encoder (merely useful for proper BOM handling) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment