bpo-31311: Fix a SystemError and a crash in ctypes._CData.__setstate_… · python/cpython@57c2561 (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 |
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) |