Commits

Thomas Heller committed 35c4fda

Fix bug #1518190: accept any integer or long value in the
ctypes.c_void_p constructor.

Comments (0)

Files changed (3)

Lib/ctypes/test/test_pointers.py

         q = pointer(y)
         pp[0] = q         # <==
         self.failUnlessEqual(p[0], 6)
+    def test_c_void_p(self):
+        # http://sourceforge.net/tracker/?func=detail&aid=1518190&group_id=5470&atid=105470
+        if sizeof(c_void_p) == 4:
+            self.failUnlessEqual(c_void_p(0xFFFFFFFFL).value,
+                                 c_void_p(-1).value)
+            self.failUnlessEqual(c_void_p(0xFFFFFFFFFFFFFFFFL).value,
+                                 c_void_p(-1).value)
+        elif sizeof(c_void_p) == 8:
+            self.failUnlessEqual(c_void_p(0xFFFFFFFFL).value,
+                                 0xFFFFFFFFL)
+            self.failUnlessEqual(c_void_p(0xFFFFFFFFFFFFFFFFL).value,
+                                 c_void_p(-1).value)
+            self.failUnlessEqual(c_void_p(0xFFFFFFFFFFFFFFFFFFFFFFFFL).value,
+                                 c_void_p(-1).value)
+
+        self.assertRaises(TypeError, c_void_p, 3.14) # make sure floats are NOT accepted
+        self.assertRaises(TypeError, c_void_p, object()) # nor other objects
 
 if __name__ == '__main__':
     unittest.main()
 Library
 -------
 
+- Bug #1518190: The ctypes.c_void_p constructor now accepts any
+  integer or long, without range checking.
+
 - Bug #1508010: msvccompiler now requires the DISTUTILS_USE_SDK 
   environment variable to be set in order to the SDK environment
   for finding the compiler, include files, etc.

Modules/_ctypes/cfield.c

 		*(void **)ptr = NULL;
 		_RET(value);
 	}
-	
-	v = PyLong_AsVoidPtr(value);
-	if (PyErr_Occurred()) {
-		/* prevent the SystemError: bad argument to internal function */
-		if (!PyInt_Check(value) && !PyLong_Check(value)) {
-			PyErr_SetString(PyExc_TypeError,
-					"cannot be converted to pointer");
-		}
+
+	if (!PyInt_Check(value) && !PyLong_Check(value)) {
+		PyErr_SetString(PyExc_TypeError,
+				"cannot be converted to pointer");
 		return NULL;
 	}
+
+#if SIZEOF_VOID_P <= SIZEOF_LONG
+	v = (void *)PyInt_AsUnsignedLongMask(value);
+#else
+#ifndef HAVE_LONG_LONG
+#   error "PyLong_AsVoidPtr: sizeof(void*) > sizeof(long), but no long long"
+#elif SIZEOF_LONG_LONG < SIZEOF_VOID_P
+#   error "PyLong_AsVoidPtr: sizeof(PY_LONG_LONG) < sizeof(void*)"
+#endif
+	v = (void *)PyInt_AsUnsignedLongLongMask(value);
+#endif
+
+	if (PyErr_Occurred())
+		return NULL;
+
 	*(void **)ptr = v;
 	_RET(value);
 }