summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorVinay Sajip <vinay_sajip@yahoo.co.uk>2017-02-20 00:16:33 (GMT)
committerGitHub <noreply@github.com>2017-02-20 00:16:33 (GMT)
commita86339b83fbd0932e0529a3c91935e997a234582 (patch)
tree34b0c69efbc4097a78b6292050460d8ba1df6265 /Modules
parent3eea8c67fa870c6e2b7a521d292afe7fe3e95f58 (diff)
downloadcpython-a86339b83fbd0932e0529a3c91935e997a234582.zip
cpython-a86339b83fbd0932e0529a3c91935e997a234582.tar.gz
cpython-a86339b83fbd0932e0529a3c91935e997a234582.tar.bz2
Fixed bpo-29565: Corrected ctypes passing of large structs by value on Windows AMD64. (#168)
* Fixed bpo-29565: Corrected ctypes passing of large structs by value. Added code and test to check that when a structure passed by value is large enough to need to be passed by reference, a copy of the original structure is passed. The callee updates the passed-in value, and the test verifies that the caller's copy is unchanged. A similar change was also added to the test added for bpo-20160 (that test was passing, but the changes should guard against regressions). * Reverted unintended whitespace changes.
Diffstat (limited to 'Modules')
-rw-r--r--Modules/_ctypes/_ctypes_test.c13
-rw-r--r--Modules/_ctypes/libffi_msvc/ffi.c10
2 files changed, 23 insertions, 0 deletions
diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c
index 92b5adb..9410c7f 100644
--- a/Modules/_ctypes/_ctypes_test.c
+++ b/Modules/_ctypes/_ctypes_test.c
@@ -44,6 +44,19 @@ _testfunc_cbk_large_struct(Test in, void (*func)(Test))
func(in);
}
+/*
+ * See issue 29565. Update a structure passed by value;
+ * the caller should not see any change.
+ */
+
+EXPORT(void)
+_testfunc_large_struct_update_value(Test in)
+{
+ in.first = 0x0badf00d;
+ in.second = 0x0badf00d;
+ in.third = 0x0badf00d;
+}
+
EXPORT(void)testfunc_array(int values[4])
{
printf("testfunc_array %d %d %d %d\n",
diff --git a/Modules/_ctypes/libffi_msvc/ffi.c b/Modules/_ctypes/libffi_msvc/ffi.c
index 1d82929..91a27dc 100644
--- a/Modules/_ctypes/libffi_msvc/ffi.c
+++ b/Modules/_ctypes/libffi_msvc/ffi.c
@@ -239,6 +239,16 @@ ffi_call(/*@dependent@*/ ffi_cif *cif,
break;
#else
case FFI_SYSV:
+ /* If a single argument takes more than 8 bytes,
+ then a copy is passed by reference. */
+ for (unsigned i = 0; i < cif->nargs; i++) {
+ size_t z = cif->arg_types[i]->size;
+ if (z > 8) {
+ void *temp = alloca(z);
+ memcpy(temp, avalue[i], z);
+ avalue[i] = temp;
+ }
+ }
/*@-usedef@*/
return ffi_call_AMD64(ffi_prep_args, &ecif, cif->bytes,
cif->flags, ecif.rvalue, fn);