File tree 3 files changed +33
-14
lines changed
Filter options
3 files changed +33
-14
lines changed
Original file line number Diff line number Diff line change @@ -1148,6 +1148,21 @@ def test_disallow_instantiation(self):
1148
1148
_io = self ._io
1149
1149
support .check_disallow_instantiation (self , _io ._BytesIOBuffer )
1150
1150
1151
+ def test_stringio_setstate (self ):
1152
+ # gh-127182: Calling __setstate__() with invalid arguments must not crash
1153
+ obj = self ._io .StringIO ()
1154
+ with self .assertRaisesRegex (
1155
+ TypeError ,
1156
+ 'initial_value must be str or None, not int' ,
1157
+ ):
1158
+ obj .__setstate__ ((1 , '' , 0 , {}))
1159
+
1160
+ obj .__setstate__ ((None , '' , 0 , {})) # should not crash
1161
+ self .assertEqual (obj .getvalue (), '' )
1162
+
1163
+ obj .__setstate__ (('' , '' , 0 , {}))
1164
+ self .assertEqual (obj .getvalue (), '' )
1165
+
1151
1166
class PyIOTest (IOTest ):
1152
1167
pass
1153
1168
Original file line number Diff line number Diff line change
1
+ Fix :meth: `!io.StringIO.__setstate__ ` crash, when :const: `None ` was passed as
2
+ the first value.
Original file line number Diff line number Diff line change @@ -908,23 +908,25 @@ _io_StringIO___setstate___impl(stringio *self, PyObject *state)
908
908
once by __init__. So we do not take any chance and replace object's
909
909
buffer completely. */
910
910
{
911
- PyObject * item ;
912
- Py_UCS4 * buf ;
913
- Py_ssize_t bufsize ;
914
-
915
- item = PyTuple_GET_ITEM (state , 0 );
916
- buf = PyUnicode_AsUCS4Copy (item );
917
- if (buf == NULL )
918
- return NULL ;
919
- bufsize = PyUnicode_GET_LENGTH (item );
911
+ PyObject * item = PyTuple_GET_ITEM (state , 0 );
912
+ if (PyUnicode_Check (item )) {
913
+ Py_UCS4 * buf = PyUnicode_AsUCS4Copy (item );
914
+ if (buf == NULL )
915
+ return NULL ;
916
+ Py_ssize_t bufsize = PyUnicode_GET_LENGTH (item );
920
917
921
- if (resize_buffer (self , bufsize ) < 0 ) {
918
+ if (resize_buffer (self , bufsize ) < 0 ) {
919
+ PyMem_Free (buf );
920
+ return NULL ;
921
+ }
922
+ memcpy (self -> buf , buf , bufsize * sizeof (Py_UCS4 ));
922
923
PyMem_Free (buf );
923
- return NULL ;
924
+ self -> string_size = bufsize ;
925
+ }
926
+ else {
927
+ assert (item == Py_None );
928
+ self -> string_size = 0 ;
924
929
}
925
- memcpy (self -> buf , buf , bufsize * sizeof (Py_UCS4 ));
926
- PyMem_Free (buf );
927
- self -> string_size = bufsize ;
928
930
}
929
931
930
932
/* Set carefully the position value. Alternatively, we could use the seek
You can’t perform that action at this time.
0 commit comments