mirror of
https://github.com/python/cpython.git
synced 2025-07-23 19:25:40 +00:00
[3.13] gh-127182: Fix io.StringIO.__setstate__
crash when None
is the first value (GH-127219) (#127262)
gh-127182: Fix `io.StringIO.__setstate__` crash when `None` is the first value (GH-127219)
(cherry picked from commit a2ee899682
)
Co-authored-by: sobolevn <mail@sobolevn.me>
Co-authored-by: Victor Stinner <vstinner@python.org>
This commit is contained in:
parent
f0c47ea22e
commit
a1b9663c41
3 changed files with 33 additions and 14 deletions
|
@ -1148,6 +1148,21 @@ class TestIOCTypes(unittest.TestCase):
|
||||||
_io = self._io
|
_io = self._io
|
||||||
support.check_disallow_instantiation(self, _io._BytesIOBuffer)
|
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):
|
class PyIOTest(IOTest):
|
||||||
pass
|
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
|
once by __init__. So we do not take any chance and replace object's
|
||||||
buffer completely. */
|
buffer completely. */
|
||||||
{
|
{
|
||||||
PyObject *item;
|
PyObject *item = PyTuple_GET_ITEM(state, 0);
|
||||||
Py_UCS4 *buf;
|
if (PyUnicode_Check(item)) {
|
||||||
Py_ssize_t bufsize;
|
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);
|
if (resize_buffer(self, bufsize) < 0) {
|
||||||
buf = PyUnicode_AsUCS4Copy(item);
|
PyMem_Free(buf);
|
||||||
if (buf == NULL)
|
return NULL;
|
||||||
return NULL;
|
}
|
||||||
bufsize = PyUnicode_GET_LENGTH(item);
|
memcpy(self->buf, buf, bufsize * sizeof(Py_UCS4));
|
||||||
|
|
||||||
if (resize_buffer(self, bufsize) < 0) {
|
|
||||||
PyMem_Free(buf);
|
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
|
/* Set carefully the position value. Alternatively, we could use the seek
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue