Fix bug #1518190: accept any integer or long value in the
ctypes.c_void_p constructor.
diff --git a/Lib/ctypes/test/test_pointers.py b/Lib/ctypes/test/test_pointers.py
index a7a2802..586655a 100644
--- a/Lib/ctypes/test/test_pointers.py
+++ b/Lib/ctypes/test/test_pointers.py
@@ -157,6 +157,23 @@
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()
diff --git a/Misc/NEWS b/Misc/NEWS
index 6f28dbc..1a976a1 100644
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -39,6 +39,9 @@
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.
diff --git a/Modules/_ctypes/cfield.c b/Modules/_ctypes/cfield.c
index c5895f0..b147ae2 100644
--- a/Modules/_ctypes/cfield.c
+++ b/Modules/_ctypes/cfield.c
@@ -1486,16 +1486,27 @@
*(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);
}