From 1ad576c2672aa8d6cae2bf3427fbcd9e75dc564a Mon Sep 17 00:00:00 2001 From: Thomas Heller Date: Fri, 4 May 2007 19:54:22 +0000 Subject: [PATCH] Do not truncate 64-bit pointers to 32-bit integers. Fixes SF #1703286, will backport to release25-maint. --- Lib/ctypes/test/test_loading.py | 27 +++++++++++++++++++++++++++ Modules/_ctypes/callproc.c | 26 +++++++++++++------------- Modules/_ctypes/ctypes.h | 6 ++++++ 3 files changed, 46 insertions(+), 13 deletions(-) diff --git a/Lib/ctypes/test/test_loading.py b/Lib/ctypes/test/test_loading.py index 28c83fd4a9d..ee34754d947 100644 --- a/Lib/ctypes/test/test_loading.py +++ b/Lib/ctypes/test/test_loading.py @@ -58,6 +58,33 @@ class LoaderTest(unittest.TestCase): windll.LoadLibrary("coredll").GetModuleHandleW WinDLL("coredll").GetModuleHandleW + def test_1703286_A(self): + from _ctypes import LoadLibrary, FreeLibrary + # On winXP 64-bit, advapi32 loads at an address that does + # NOT fit into a 32-bit integer. FreeLibrary must be able + # to accept this address. + + # These are tests for http://www.python.org/sf/1703286 + handle = LoadLibrary("advapi32") + FreeLibrary(handle) + + def test_1703286_B(self): + # Since on winXP 64-bit advapi32 loads like described + # above, the (arbitrarily selected) CloseEventLog function + # also has a high address. 'call_function' should accept + # addresses so large. + from _ctypes import call_function + advapi32 = windll.advapi32 + # Calling CloseEventLog with a NULL argument should fail, + # but the call should not segfault or so. + self.failUnlessEqual(0, advapi32.CloseEventLog(None)) + windll.kernel32.GetProcAddress.argtypes = c_void_p, c_char_p + windll.kernel32.GetProcAddress.restype = c_void_p + proc = windll.kernel32.GetProcAddress(advapi32._handle, "CloseEventLog") + self.failUnless(proc) + # This is the real test: call the function via 'call_function' + self.failUnlessEqual(0, call_function(proc, (None,))) + def test_load_ordinal_functions(self): import _ctypes_test dll = WinDLL(_ctypes_test.__file__) diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c index b7dda48a867..a8d4ce16017 100644 --- a/Modules/_ctypes/callproc.c +++ b/Modules/_ctypes/callproc.c @@ -1128,10 +1128,10 @@ static char free_library_doc[] = Free the handle of an executable previously loaded by LoadLibrary.\n"; static PyObject *free_library(PyObject *self, PyObject *args) { - HMODULE hMod; - if (!PyArg_ParseTuple(args, "i:FreeLibrary", &hMod)) + void *hMod; + if (!PyArg_ParseTuple(args, PY_VOID_P_CODE ":FreeLibrary", &hMod)) return NULL; - if (!FreeLibrary(hMod)) + if (!FreeLibrary((HMODULE)hMod)) return PyErr_SetFromWindowsErr(GetLastError()); Py_INCREF(Py_None); return Py_None; @@ -1250,11 +1250,11 @@ static PyObject *py_dl_open(PyObject *self, PyObject *args) static PyObject *py_dl_close(PyObject *self, PyObject *args) { - int handle; + void *handle; - if (!PyArg_ParseTuple(args, "i:dlclose", &handle)) + if (!PyArg_ParseTuple(args, PY_VOID_P_CODE ":dlclose", &handle)) return NULL; - if (dlclose((void*)handle)) { + if (dlclose(handle)) { PyErr_SetString(PyExc_OSError, ctypes_dlerror()); return NULL; @@ -1266,10 +1266,10 @@ static PyObject *py_dl_close(PyObject *self, PyObject *args) static PyObject *py_dl_sym(PyObject *self, PyObject *args) { char *name; - int handle; + void *handle; void *ptr; - if (!PyArg_ParseTuple(args, "is:dlsym", &handle, &name)) + if (!PyArg_ParseTuple(args, PY_VOID_P_CODE "s:dlsym", &handle, &name)) return NULL; ptr = ctypes_dlsym((void*)handle, name); if (!ptr) { @@ -1277,7 +1277,7 @@ static PyObject *py_dl_sym(PyObject *self, PyObject *args) ctypes_dlerror()); return NULL; } - return Py_BuildValue("i", ptr); + return PyLong_FromVoidPtr(ptr); } #endif @@ -1289,12 +1289,12 @@ static PyObject *py_dl_sym(PyObject *self, PyObject *args) static PyObject * call_function(PyObject *self, PyObject *args) { - int func; + void *func; PyObject *arguments; PyObject *result; if (!PyArg_ParseTuple(args, - "iO!", + PY_VOID_P_CODE "O!", &func, &PyTuple_Type, &arguments)) return NULL; @@ -1320,12 +1320,12 @@ call_function(PyObject *self, PyObject *args) static PyObject * call_cdeclfunction(PyObject *self, PyObject *args) { - int func; + void *func; PyObject *arguments; PyObject *result; if (!PyArg_ParseTuple(args, - "iO!", + PY_VOID_P_CODE "O!", &func, &PyTuple_Type, &arguments)) return NULL; diff --git a/Modules/_ctypes/ctypes.h b/Modules/_ctypes/ctypes.h index 0af78510208..5fb603075d3 100644 --- a/Modules/_ctypes/ctypes.h +++ b/Modules/_ctypes/ctypes.h @@ -23,6 +23,12 @@ typedef int Py_ssize_t; #define PY_LONG_LONG LONG_LONG #endif +#if SIZEOF_VOID_P == SIZEOF_LONG +#define PY_VOID_P_CODE "k" +#elif defined(HAVE_LONG_LONG) && (SIZEOF_VOID_P == SIZEOF_LONG_LONG) +#define PY_VOID_P_CODE "K" +#endif + typedef struct tagPyCArgObject PyCArgObject; typedef struct tagCDataObject CDataObject; typedef PyObject *(* GETFUNC)(void *, unsigned size);