]> granicus.if.org Git - python/commitdiff
Fix bug #1598620: A ctypes structure cannot contain itself.
authorThomas Heller <theller@ctypes.org>
Fri, 24 Nov 2006 19:00:39 +0000 (19:00 +0000)
committerThomas Heller <theller@ctypes.org>
Fri, 24 Nov 2006 19:00:39 +0000 (19:00 +0000)
Backport from trunk.

Lib/ctypes/test/test_structures.py
Misc/NEWS
Modules/_ctypes/stgdict.c

index 8a4531db936dc3d43ad8a9111e2a258bdb18d586..613163d0ccae00fec2e8d290c631e7927216eb69 100644 (file)
@@ -381,5 +381,35 @@ class PointerMemberTestCase(unittest.TestCase):
         s.p = None
         self.failUnlessEqual(s.x, 12345678)
 
+class TestRecursiveStructure(unittest.TestCase):
+    def test_contains_itself(self):
+        class Recursive(Structure):
+            pass
+
+        try:
+            Recursive._fields_ = [("next", Recursive)]
+        except AttributeError, details:
+            self.failUnless("Structure or union cannot contain itself" in
+                            str(details))
+        else:
+            self.fail("Structure or union cannot contain itself")
+
+
+    def test_vice_versa(self):
+        class First(Structure):
+            pass
+        class Second(Structure):
+            pass
+
+        First._fields_ = [("second", Second)]
+
+        try:
+            Second._fields_ = [("first", First)]
+        except AttributeError, details:
+            self.failUnless("_fields_ is final" in
+                            str(details))
+        else:
+            self.fail("AttributeError not raised")
+
 if __name__ == '__main__':
     unittest.main()
index 0cf1c4bf821f609a9f045d36bfe1056553dfc1c0..9b8fc274fcc9ef951e1f1de3cefd084f7675e3b4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -70,6 +70,8 @@ Core and builtins
 Extension Modules
 -----------------
 
+- Bug #1598620: A ctypes Structure cannot contain itself.
 - Bug #1588217: don't parse "= " as a soft line break in binascii's
   a2b_qp() function, instead leave it in the string as quopri.decode()
   does.
index d701f9ec5d7c2b32fbb5432b2d51ec54879fa52d..8fd9a1e576382bb0a0de401c160a48959d851023 100644 (file)
@@ -339,14 +339,14 @@ StructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
        stgdict = PyType_stgdict(type);
        if (!stgdict)
                return -1;
+       /* If this structure/union is already marked final we cannot assign
+          _fields_ anymore. */
+
        if (stgdict->flags & DICTFLAG_FINAL) {/* is final ? */
                PyErr_SetString(PyExc_AttributeError,
                                "_fields_ is final");
                return -1;
        }
-       /* XXX This should probably be moved to a point when all this
-          stuff is sucessfully finished. */
-       stgdict->flags |= DICTFLAG_FINAL;       /* set final */
 
        if (stgdict->ffi_type_pointer.elements)
                PyMem_Free(stgdict->ffi_type_pointer.elements);
@@ -480,5 +480,15 @@ StructUnionType_update_stgdict(PyObject *type, PyObject *fields, int isStruct)
        stgdict->size = size;
        stgdict->align = total_align;
        stgdict->length = len;  /* ADD ffi_ofs? */
+
+       /* We did check that this flag was NOT set above, it must not
+          have been set until now. */
+       if (stgdict->flags & DICTFLAG_FINAL) {
+               PyErr_SetString(PyExc_AttributeError,
+                               "Structure or union cannot contain itself");
+               return -1;
+       }
+       stgdict->flags |= DICTFLAG_FINAL;
+
        return MakeAnonFields(type);
 }