mirror of https://github.com/python/cpython.git
gh-127182: Fix `io.StringIO.__setstate__` crash when `None` is the first value (#127219)
Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
d3da04bfc9
commit
a2ee899682
|
@ -1148,6 +1148,21 @@ def test_disallow_instantiation(self):
|
|||
_io = self._io
|
||||
support.check_disallow_instantiation(self, _io._BytesIOBuffer)
|
||||
|
||||
def test_stringio_setstate(self):
|
||||
# gh-127182: Calling __setstate__() with invalid arguments must not crash
|
||||
obj = self._io.StringIO()
|
||||
with self.assertRaisesRegex(
|
||||
TypeError,
|
||||
'initial_value must be str or None, not int',
|
||||
):
|
||||
obj.__setstate__((1, '', 0, {}))
|
||||
|
||||
obj.__setstate__((None, '', 0, {})) # should not crash
|
||||
self.assertEqual(obj.getvalue(), '')
|
||||
|
||||
obj.__setstate__(('', '', 0, {}))
|
||||
self.assertEqual(obj.getvalue(), '')
|
||||
|
||||
class PyIOTest(IOTest):
|
||||
pass
|
||||
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
Fix :meth:`!io.StringIO.__setstate__` crash, when :const:`None` was passed as
|
||||
the first value.
|
|
@ -908,23 +908,25 @@ _io_StringIO___setstate___impl(stringio *self, PyObject *state)
|
|||
once by __init__. So we do not take any chance and replace object's
|
||||
buffer completely. */
|
||||
{
|
||||
PyObject *item;
|
||||
Py_UCS4 *buf;
|
||||
Py_ssize_t bufsize;
|
||||
PyObject *item = PyTuple_GET_ITEM(state, 0);
|
||||
if (PyUnicode_Check(item)) {
|
||||
Py_UCS4 *buf = PyUnicode_AsUCS4Copy(item);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
Py_ssize_t bufsize = PyUnicode_GET_LENGTH(item);
|
||||
|
||||
item = PyTuple_GET_ITEM(state, 0);
|
||||
buf = PyUnicode_AsUCS4Copy(item);
|
||||
if (buf == NULL)
|
||||
return NULL;
|
||||
bufsize = PyUnicode_GET_LENGTH(item);
|
||||
|
||||
if (resize_buffer(self, bufsize) < 0) {
|
||||
if (resize_buffer(self, bufsize) < 0) {
|
||||
PyMem_Free(buf);
|
||||
return NULL;
|
||||
}
|
||||
memcpy(self->buf, buf, bufsize * sizeof(Py_UCS4));
|
||||
PyMem_Free(buf);
|
||||
return NULL;
|
||||
self->string_size = bufsize;
|
||||
}
|
||||
else {
|
||||
assert(item == Py_None);
|
||||
self->string_size = 0;
|
||||
}
|
||||
memcpy(self->buf, buf, bufsize * sizeof(Py_UCS4));
|
||||
PyMem_Free(buf);
|
||||
self->string_size = bufsize;
|
||||
}
|
||||
|
||||
/* Set carefully the position value. Alternatively, we could use the seek
|
||||
|
|
Loading…
Reference in New Issue