[2.7] bpo-31311: Fix a SystemError and a crash in ctypes._CData.__set… · python/cpython@81691b0 (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, sys
2 2 from ctypes.test import need_symbol
3 +import test.support
3 4
4 5 class SimpleTypesTestCase(unittest.TestCase):
5 6
@@ -175,6 +176,26 @@ def from_param(cls, obj):
175 176 self.assertRaises(ArgumentError, func, 99)
176 177
177 178
179 +@test.support.cpython_only
180 +def test_issue31311(self):
181 +# __setstate__ should neither raise a SystemError nor crash in case
182 +# of a bad __dict__.
183 +from ctypes import Structure
184 +
185 +class BadStruct(Structure):
186 +@property
187 +def __dict__(self):
188 +pass
189 +with self.assertRaises(TypeError):
190 +BadStruct().__setstate__({}, b'foo')
191 +
192 +class WorseStruct(Structure):
193 +@property
194 +def __dict__(self):
195 +1/0
196 +with self.assertRaises(ZeroDivisionError):
197 +WorseStruct().__setstate__({}, b'foo')
198 +
178 199 ################################################################
179 200
180 201 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
@@ -2786,6 +2786,16 @@ PyCData_setstate(PyObject *_self, PyObject *args)
2786 2786 len = self->b_size;
2787 2787 memmove(self->b_ptr, data, len);
2788 2788 mydict = PyObject_GetAttrString(_self, "__dict__");
2789 +if (mydict == NULL) {
2790 +return NULL;
2791 + }
2792 +if (!PyDict_Check(mydict)) {
2793 +PyErr_Format(PyExc_TypeError,
2794 +"%.200s.__dict__ must be a dictionary, not %.200s",
2795 +Py_TYPE(_self)->tp_name, Py_TYPE(mydict)->tp_name);
2796 +Py_DECREF(mydict);
2797 +return NULL;
2798 + }
2789 2799 res = PyDict_Update(mydict, dict);
2790 2800 Py_DECREF(mydict);
2791 2801 if (res == -1)