summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorThomas Heller <theller@ctypes.org>2006-08-11 19:55:35 (GMT)
committerThomas Heller <theller@ctypes.org>2006-08-11 19:55:35 (GMT)
commit2a899c8b767144e809418fd04f83e4e5789084cd (patch)
tree6fb25c2395ae8700396b4c03b7d35af2c1113a74 /Modules
parent975c8bb515d8b1765b36ac90a92cffea8b38b7db (diff)
downloadcpython-2a899c8b767144e809418fd04f83e4e5789084cd.zip
cpython-2a899c8b767144e809418fd04f83e4e5789084cd.tar.gz
cpython-2a899c8b767144e809418fd04f83e4e5789084cd.tar.bz2
When a ctypes C callback function is called, zero out the result
storage before converting the result to C data. See the comment in the code for details. Provide a better context for errors when the conversion of a callback function's result cannot be converted.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_ctypes/callbacks.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/Modules/_ctypes/callbacks.c b/Modules/_ctypes/callbacks.c
index c091d88..3ad6fb4 100644
--- a/Modules/_ctypes/callbacks.c
+++ b/Modules/_ctypes/callbacks.c
@@ -205,14 +205,24 @@ if (x == NULL) _AddTraceback(what, __FILE__, __LINE__ - 1), PyErr_Print()
result = PyObject_CallObject(callable, arglist);
CHECK("'calling callback function'", result);
+#ifdef WORDS_BIGENDIAN
+ /* See the corresponding code in callproc.c, around line 961 */
+ if (restype->type != FFI_TYPE_FLOAT && restype->size < sizeof(ffi_arg))
+ mem = (char *)mem + sizeof(ffi_arg) - restype->size;
+#endif
+ /* The code that converts 'result' into C data is not executed when
+ 'callable' returns Py_None, so we zero out the memory that will
+ receive the C return data to not return random data.
+
+ Cleaner would be to call 'setfunc' anyway and complain with
+ PyErr_WriteUnraisable(), but ctypes has always accepted a Py_None
+ return value for *any* 'restype' and it would probably break too
+ much code if this is changed now.
+ */
+ memset(mem, 0, restype->size);
if ((restype != &ffi_type_void) && result && result != Py_None) {
PyObject *keep;
assert(setfunc);
-#ifdef WORDS_BIGENDIAN
- /* See the corresponding code in callproc.c, around line 961 */
- if (restype->type != FFI_TYPE_FLOAT && restype->size < sizeof(ffi_arg))
- mem = (char *)mem + sizeof(ffi_arg) - restype->size;
-#endif
keep = setfunc(mem, result, 0);
CHECK("'converting callback result'", keep);
/* keep is an object we have to keep alive so that the result
@@ -225,13 +235,13 @@ if (x == NULL) _AddTraceback(what, __FILE__, __LINE__ - 1), PyErr_Print()
itself knows how to manage the refcount of these objects.
*/
if (keep == NULL) /* Could not convert callback result. */
- PyErr_WriteUnraisable(Py_None);
+ PyErr_WriteUnraisable(callable);
else if (keep == Py_None) /* Nothing to keep */
Py_DECREF(keep);
else if (setfunc != getentry("O")->setfunc) {
if (-1 == PyErr_Warn(PyExc_RuntimeWarning,
"memory leak in callback function."))
- PyErr_WriteUnraisable(Py_None);
+ PyErr_WriteUnraisable(callable);
}
}
Py_XDECREF(result);