summaryrefslogtreecommitdiffstats
path: root/Modules
diff options
context:
space:
mode:
authorVinay Sajip <vinay_sajip@yahoo.co.uk>2017-02-22 06:21:17 (GMT)
committerGitHub <noreply@github.com>2017-02-22 06:21:17 (GMT)
commit3cc5817cfaf5663645f4ee447eaed603d2ad290a (patch)
tree34797bd494eb8e1a2a77bdee100c682fb8055362 /Modules
parentb067a5eef7fdf69264d3578654996fc3755df4ea (diff)
downloadcpython-3cc5817cfaf5663645f4ee447eaed603d2ad290a.zip
cpython-3cc5817cfaf5663645f4ee447eaed603d2ad290a.tar.gz
cpython-3cc5817cfaf5663645f4ee447eaed603d2ad290a.tar.bz2
Fixed bpo-29565: Corrected ctypes passing of large structs by value on Windows AMD64. (#168) (#220)
Fixed bpo-29565: Corrected ctypes passing of large structs by value. (cherry picked from commit a86339b83fbd0932e0529a3c91935e997a234582)
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 629ddf6..59d56d0 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);