diff options
author | Vinay Sajip <vinay_sajip@yahoo.co.uk> | 2017-02-20 00:16:33 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-20 00:16:33 (GMT) |
commit | a86339b83fbd0932e0529a3c91935e997a234582 (patch) | |
tree | 34b0c69efbc4097a78b6292050460d8ba1df6265 /Modules/_ctypes | |
parent | 3eea8c67fa870c6e2b7a521d292afe7fe3e95f58 (diff) | |
download | cpython-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/_ctypes')
-rw-r--r-- | Modules/_ctypes/_ctypes_test.c | 13 | ||||
-rw-r--r-- | Modules/_ctypes/libffi_msvc/ffi.c | 10 |
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); |