[Python-checkins] bpo-31311: Fix a SystemError and a crash in ctypes._CData.__setstate__(), in case of a bad __dict__. (#3254)

Serhiy Storchaka webhook-mailer at python.org
Mon Sep 25 04:09:14 EDT 2017


https://github.com/python/cpython/commit/57c2561c8c5663aef55b00e3f29cba575ff36ccd
commit: 57c2561c8c5663aef55b00e3f29cba575ff36ccd
branch: master
author: Oren Milman <orenmn at gmail.com>
committer: Serhiy Storchaka <storchaka at gmail.com>
date: 2017-09-25T11:09:11+03:00
summary:

bpo-31311: Fix a SystemError and a crash in ctypes._CData.__setstate__(), in case of a bad __dict__. (#3254)

files:
A Misc/NEWS.d/next/Core and Builtins/2017-08-31-17-52-56.bpo-31311.bNE2l-.rst
M Lib/ctypes/test/test_parameters.py
M Modules/_ctypes/_ctypes.c

diff --git a/Lib/ctypes/test/test_parameters.py b/Lib/ctypes/test/test_parameters.py
index 4eaa15aff42..e4c25fd880c 100644
--- a/Lib/ctypes/test/test_parameters.py
+++ b/Lib/ctypes/test/test_parameters.py
@@ -1,5 +1,6 @@
 import unittest
 from ctypes.test import need_symbol
+import test.support
 
 class SimpleTypesTestCase(unittest.TestCase):
 
@@ -180,6 +181,26 @@ def test_abstract(self):
         self.assertRaises(TypeError, _Pointer.from_param, 42)
         self.assertRaises(TypeError, _SimpleCData.from_param, 42)
 
+    @test.support.cpython_only
+    def test_issue31311(self):
+        # __setstate__ should neither raise a SystemError nor crash in case
+        # of a bad __dict__.
+        from ctypes import Structure
+
+        class BadStruct(Structure):
+            @property
+            def __dict__(self):
+                pass
+        with self.assertRaises(TypeError):
+            BadStruct().__setstate__({}, b'foo')
+
+        class WorseStruct(Structure):
+            @property
+            def __dict__(self):
+                1/0
+        with self.assertRaises(ZeroDivisionError):
+            WorseStruct().__setstate__({}, b'foo')
+
 ################################################################
 
 if __name__ == '__main__':
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-08-31-17-52-56.bpo-31311.bNE2l-.rst b/Misc/NEWS.d/next/Core and Builtins/2017-08-31-17-52-56.bpo-31311.bNE2l-.rst
new file mode 100644
index 00000000000..db51cd2d586
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2017-08-31-17-52-56.bpo-31311.bNE2l-.rst	
@@ -0,0 +1,2 @@
+Fix a crash in the ``__setstate__()`` method of `ctypes._CData`, in case of
+a bad ``__dict__``. Patch by Oren Milman.
diff --git a/Modules/_ctypes/_ctypes.c b/Modules/_ctypes/_ctypes.c
index 8afb8cc1f16..eaaedfa413f 100644
--- a/Modules/_ctypes/_ctypes.c
+++ b/Modules/_ctypes/_ctypes.c
@@ -2674,6 +2674,16 @@ PyCData_setstate(PyObject *myself, PyObject *args)
         len = self->b_size;
     memmove(self->b_ptr, data, len);
     mydict = PyObject_GetAttrString(myself, "__dict__");
+    if (mydict == NULL) {
+        return NULL;
+    }
+    if (!PyDict_Check(mydict)) {
+        PyErr_Format(PyExc_TypeError,
+                     "%.200s.__dict__ must be a dictionary, not %.200s",
+                     Py_TYPE(myself)->tp_name, Py_TYPE(mydict)->tp_name);
+        Py_DECREF(mydict);
+        return NULL;
+    }
     res = PyDict_Update(mydict, dict);
     Py_DECREF(mydict);
     if (res == -1)



More information about the Python-checkins mailing list