aboutsummaryrefslogtreecommitdiffstats
path: root/main/python3/bpo-30353.patch
diff options
context:
space:
mode:
authorTimo Teräs <timo.teras@iki.fi>2017-08-30 08:40:35 +0000
committerTimo Teräs <timo.teras@iki.fi>2017-08-30 08:41:26 +0000
commite768f9eb900df39eaa9c8cbe4037d7a7637cf1d4 (patch)
tree476c49c6870128933b1e84fe403f0ff3cff63167 /main/python3/bpo-30353.patch
parentd38ae19d17f18ad5ce17ad0ea5bb0f6388039a6c (diff)
downloadaports-e768f9eb900df39eaa9c8cbe4037d7a7637cf1d4.tar.bz2
aports-e768f9eb900df39eaa9c8cbe4037d7a7637cf1d4.tar.xz
main/python3: apply bpo-30353 to fix aarch64 ctypes issue
Diffstat (limited to 'main/python3/bpo-30353.patch')
-rw-r--r--main/python3/bpo-30353.patch133
1 files changed, 133 insertions, 0 deletions
diff --git a/main/python3/bpo-30353.patch b/main/python3/bpo-30353.patch
new file mode 100644
index 0000000000..28fc93eef0
--- /dev/null
+++ b/main/python3/bpo-30353.patch
@@ -0,0 +1,133 @@
+https://github.com/python/cpython/commit/9ba3aa4d02a110d1a1ea464a8aff3be7dd9c63c3.patch
+
+From 9ba3aa4d02a110d1a1ea464a8aff3be7dd9c63c3 Mon Sep 17 00:00:00 2001
+From: Erik Bray <erik.m.bray@gmail.com>
+Date: Wed, 7 Jun 2017 18:42:24 +0100
+Subject: [PATCH] bpo-30353: Fix pass by value for structs on 64-bit
+ Cygwin/MinGW (GH-1559)
+
+---
+ Lib/ctypes/test/test_as_parameter.py | 4 ++++
+ Lib/ctypes/test/test_structures.py | 22 ++++++++++++++++++++++
+ Modules/_ctypes/_ctypes_test.c | 18 ++++++++++++++++++
+ Modules/_ctypes/callproc.c | 23 +++++++++++++++++++++--
+ 4 files changed, 65 insertions(+), 2 deletions(-)
+
+diff --git a/Lib/ctypes/test/test_as_parameter.py b/Lib/ctypes/test/test_as_parameter.py
+index 2a3484bec01..a2640575a07 100644
+--- a/Lib/ctypes/test/test_as_parameter.py
++++ b/Lib/ctypes/test/test_as_parameter.py
+@@ -169,6 +169,10 @@ class S2H(Structure):
+ s2h = dll.ret_2h_func(self.wrap(inp))
+ self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
+
++ # Test also that the original struct was unmodified (i.e. was passed by
++ # value)
++ self.assertEqual((inp.x, inp.y), (99, 88))
++
+ def test_struct_return_8H(self):
+ class S8I(Structure):
+ _fields_ = [("a", c_int),
+diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py
+index 2e778fb1b43..d90c71144c9 100644
+--- a/Lib/ctypes/test/test_structures.py
++++ b/Lib/ctypes/test/test_structures.py
+@@ -417,6 +417,28 @@ class X(Structure):
+ self.assertEqual(s.second, 0xcafebabe)
+ self.assertEqual(s.third, 0x0bad1dea)
+
++ def test_pass_by_value_in_register(self):
++ class X(Structure):
++ _fields_ = [
++ ('first', c_uint),
++ ('second', c_uint)
++ ]
++
++ s = X()
++ s.first = 0xdeadbeef
++ s.second = 0xcafebabe
++ dll = CDLL(_ctypes_test.__file__)
++ func = dll._testfunc_reg_struct_update_value
++ func.argtypes = (X,)
++ func.restype = None
++ func(s)
++ self.assertEqual(s.first, 0xdeadbeef)
++ self.assertEqual(s.second, 0xcafebabe)
++ got = X.in_dll(dll, "last_tfrsuv_arg")
++ self.assertEqual(s.first, got.first)
++ self.assertEqual(s.second, got.second)
++
++
+ class PointerMemberTestCase(unittest.TestCase):
+
+ def test(self):
+diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c
+index fe0015c8013..2255e573393 100644
+--- a/Modules/_ctypes/_ctypes_test.c
++++ b/Modules/_ctypes/_ctypes_test.c
+@@ -57,6 +57,24 @@ _testfunc_large_struct_update_value(Test in)
+ ((volatile Test *)&in)->third = 0x0badf00d;
+ }
+
++typedef struct {
++ unsigned int first;
++ unsigned int second;
++} TestReg;
++
++
++EXPORT(TestReg) last_tfrsuv_arg;
++
++
++EXPORT(void)
++_testfunc_reg_struct_update_value(TestReg in)
++{
++ last_tfrsuv_arg = in;
++ ((volatile TestReg *)&in)->first = 0x0badf00d;
++ ((volatile TestReg *)&in)->second = 0x0badf00d;
++}
++
++
+ EXPORT(void)testfunc_array(int values[4])
+ {
+ printf("testfunc_array %d %d %d %d\n",
+diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
+index 0b6faf96c68..5439b939dc4 100644
+--- a/Modules/_ctypes/callproc.c
++++ b/Modules/_ctypes/callproc.c
+@@ -1039,6 +1039,13 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
+ }
+ #endif
+
++#if (defined(__x86_64__) && (defined(__MINGW64__) || defined(__CYGWIN__))) || \
++ defined(__aarch64__)
++#define CTYPES_PASS_BY_REF_HACK
++#define POW2(x) (((x & ~(x - 1)) == x) ? x : 0)
++#define IS_PASS_BY_REF(x) (x > 8 || !POW2(x))
++#endif
++
+ /*
+ * Requirements, must be ensured by the caller:
+ * - argtuple is tuple of arguments
+@@ -1136,8 +1143,20 @@ PyObject *_ctypes_callproc(PPROC pProc,
+ }
+ for (i = 0; i < argcount; ++i) {
+ atypes[i] = args[i].ffi_type;
+- if (atypes[i]->type == FFI_TYPE_STRUCT
+- )
++#ifdef CTYPES_PASS_BY_REF_HACK
++ size_t size = atypes[i]->size;
++ if (IS_PASS_BY_REF(size)) {
++ void *tmp = alloca(size);
++ if (atypes[i]->type == FFI_TYPE_STRUCT)
++ memcpy(tmp, args[i].value.p, size);
++ else
++ memcpy(tmp, (void*)&args[i].value, size);
++
++ avalues[i] = tmp;
++ }
++ else
++#endif
++ if (atypes[i]->type == FFI_TYPE_STRUCT)
+ avalues[i] = (void *)args[i].value.p;
+ else
+ avalues[i] = (void *)&args[i].value;