[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
- Misc/NEWS.d/next/Core and Builtins
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) |