bpo-31311: Fix a SystemError and a crash in ctypes._CData.__setstate_… · python/cpython@57c2561 (original) (raw)

File tree

3 files changed

lines changed

3 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
1 1 import unittest
2 2 from ctypes.test import need_symbol
3 +import test.support
3 4
4 5 class SimpleTypesTestCase(unittest.TestCase):
5 6
@@ -180,6 +181,26 @@ def test_abstract(self):
180 181 self.assertRaises(TypeError, _Pointer.from_param, 42)
181 182 self.assertRaises(TypeError, _SimpleCData.from_param, 42)
182 183
184 +@test.support.cpython_only
185 +def test_issue31311(self):
186 +# __setstate__ should neither raise a SystemError nor crash in case
187 +# of a bad __dict__.
188 +from ctypes import Structure
189 +
190 +class BadStruct(Structure):
191 +@property
192 +def __dict__(self):
193 +pass
194 +with self.assertRaises(TypeError):
195 +BadStruct().__setstate__({}, b'foo')
196 +
197 +class WorseStruct(Structure):
198 +@property
199 +def __dict__(self):
200 +1/0
201 +with self.assertRaises(ZeroDivisionError):
202 +WorseStruct().__setstate__({}, b'foo')
203 +
183 204 ################################################################
184 205
185 206 if __name__ == '__main__':
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
1 +Fix a crash in the ``__setstate__()`` method of `ctypes._CData`, in case of
2 +a bad ``__dict__``. Patch by Oren Milman.
Original file line number Diff line number Diff line change
@@ -2674,6 +2674,16 @@ PyCData_setstate(PyObject *myself, PyObject *args)
2674 2674 len = self->b_size;
2675 2675 memmove(self->b_ptr, data, len);
2676 2676 mydict = PyObject_GetAttrString(myself, "__dict__");
2677 +if (mydict == NULL) {
2678 +return NULL;
2679 + }
2680 +if (!PyDict_Check(mydict)) {
2681 +PyErr_Format(PyExc_TypeError,
2682 +"%.200s.__dict__ must be a dictionary, not %.200s",
2683 +Py_TYPE(myself)->tp_name, Py_TYPE(mydict)->tp_name);
2684 +Py_DECREF(mydict);
2685 +return NULL;
2686 + }
2677 2687 res = PyDict_Update(mydict, dict);
2678 2688 Py_DECREF(mydict);
2679 2689 if (res == -1)