Blame 00264-fix-test-failing-on-aarch64.patch

a669008
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
a669008
From: Charalampos Stratakis <cstratak@redhat.com>
a669008
Date: Mon, 30 Oct 2017 17:36:25 +0100
a669008
Subject: [PATCH] 00264: Fix test failing on aarch64
a669008
a669008
test_pass_by_value was added in Python 3.5.4 and on aarch64
a669008
it is catching an error that was there, but wasn't tested before.
a669008
Since the Python 3.5 branch is on security bug fix mode only
a669008
we backport the fix from the master branch.
a669008
Fixed upstream: http://bugs.python.org/issue29804
a669008
---
a669008
 Lib/ctypes/test/test_as_parameter.py |  4 ++++
a669008
 Lib/ctypes/test/test_structures.py   | 22 ++++++++++++++++++++++
a669008
 Modules/_ctypes/_ctypes_test.c       | 18 ++++++++++++++++++
a669008
 Modules/_ctypes/callproc.c           | 23 +++++++++++++++++++++--
a669008
 4 files changed, 65 insertions(+), 2 deletions(-)
a669008
ff4d630
diff --git a/Lib/ctypes/test/test_as_parameter.py b/Lib/ctypes/test/test_as_parameter.py
a669008
index 2a3484bec0..a2640575a0 100644
ff4d630
--- a/Lib/ctypes/test/test_as_parameter.py
ff4d630
+++ b/Lib/ctypes/test/test_as_parameter.py
a669008
@@ -169,6 +169,10 @@ class BasicWrapTestCase(unittest.TestCase):
ff4d630
         s2h = dll.ret_2h_func(self.wrap(inp))
ff4d630
         self.assertEqual((s2h.x, s2h.y), (99*2, 88*3))
ff4d630
 
ff4d630
+        # Test also that the original struct was unmodified (i.e. was passed by
ff4d630
+        # value)
ff4d630
+        self.assertEqual((inp.x, inp.y), (99, 88))
ff4d630
+
ff4d630
     def test_struct_return_8H(self):
ff4d630
         class S8I(Structure):
ff4d630
             _fields_ = [("a", c_int),
ff4d630
diff --git a/Lib/ctypes/test/test_structures.py b/Lib/ctypes/test/test_structures.py
a669008
index 2e9fc7c49c..fa7e86fa89 100644
ff4d630
--- a/Lib/ctypes/test/test_structures.py
ff4d630
+++ b/Lib/ctypes/test/test_structures.py
a669008
@@ -420,6 +420,28 @@ class StructureTestCase(unittest.TestCase):
ff4d630
         self.assertEqual(s.second, 0xcafebabe)
ff4d630
         self.assertEqual(s.third, 0x0bad1dea)
ff4d630
 
ff4d630
+    def test_pass_by_value_in_register(self):
ff4d630
+        class X(Structure):
ff4d630
+            _fields_ = [
ff4d630
+                ('first', c_uint),
ff4d630
+                ('second', c_uint)
ff4d630
+            ]
ff4d630
+
ff4d630
+        s = X()
ff4d630
+        s.first = 0xdeadbeef
ff4d630
+        s.second = 0xcafebabe
ff4d630
+        dll = CDLL(_ctypes_test.__file__)
ff4d630
+        func = dll._testfunc_reg_struct_update_value
ff4d630
+        func.argtypes = (X,)
ff4d630
+        func.restype = None
ff4d630
+        func(s)
ff4d630
+        self.assertEqual(s.first, 0xdeadbeef)
ff4d630
+        self.assertEqual(s.second, 0xcafebabe)
ff4d630
+        got = X.in_dll(dll, "last_tfrsuv_arg")
ff4d630
+        self.assertEqual(s.first, got.first)
ff4d630
+        self.assertEqual(s.second, got.second)
ff4d630
+
ff4d630
+
ff4d630
 class PointerMemberTestCase(unittest.TestCase):
ff4d630
 
ff4d630
     def test(self):
ff4d630
diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c
a669008
index e3240c526f..ed2cb6c823 100644
ff4d630
--- a/Modules/_ctypes/_ctypes_test.c
ff4d630
+++ b/Modules/_ctypes/_ctypes_test.c
ff4d630
@@ -57,6 +57,24 @@ _testfunc_large_struct_update_value(Test in)
ff4d630
     ((volatile Test *)&in)->third = 0x0badf00d;
ff4d630
 }
ff4d630
 
ff4d630
+typedef struct {
ff4d630
+    unsigned int first;
ff4d630
+    unsigned int second;
ff4d630
+} TestReg;
ff4d630
+
ff4d630
+
ff4d630
+EXPORT(TestReg) last_tfrsuv_arg;
ff4d630
+
ff4d630
+
ff4d630
+EXPORT(void)
ff4d630
+_testfunc_reg_struct_update_value(TestReg in)
ff4d630
+{
ff4d630
+    last_tfrsuv_arg = in;
ff4d630
+    ((volatile TestReg *)&in)->first = 0x0badf00d;
ff4d630
+    ((volatile TestReg *)&in)->second = 0x0badf00d;
ff4d630
+}
ff4d630
+
ff4d630
+
ff4d630
 EXPORT(void)testfunc_array(int values[4])
ff4d630
 {
ff4d630
     printf("testfunc_array %d %d %d %d\n",
ff4d630
diff --git a/Modules/_ctypes/callproc.c b/Modules/_ctypes/callproc.c
a669008
index 70e416b950..8a20e6ae13 100644
ff4d630
--- a/Modules/_ctypes/callproc.c
ff4d630
+++ b/Modules/_ctypes/callproc.c
a669008
@@ -1044,6 +1044,13 @@ GetComError(HRESULT errcode, GUID *riid, IUnknown *pIunk)
ff4d630
 }
ff4d630
 #endif
ff4d630
 
ff4d630
+#if (defined(__x86_64__) && (defined(__MINGW64__) || defined(__CYGWIN__))) || \
ff4d630
+    defined(__aarch64__)
ff4d630
+#define CTYPES_PASS_BY_REF_HACK
ff4d630
+#define POW2(x) (((x & ~(x - 1)) == x) ? x : 0)
ff4d630
+#define IS_PASS_BY_REF(x) (x > 8 || !POW2(x))
ff4d630
+#endif
ff4d630
+
ff4d630
 /*
ff4d630
  * Requirements, must be ensured by the caller:
ff4d630
  * - argtuple is tuple of arguments
a669008
@@ -1141,8 +1148,20 @@ PyObject *_ctypes_callproc(PPROC pProc,
ff4d630
     }
ff4d630
     for (i = 0; i < argcount; ++i) {
ff4d630
         atypes[i] = args[i].ffi_type;
ff4d630
-        if (atypes[i]->type == FFI_TYPE_STRUCT
ff4d630
-            )
ff4d630
+#ifdef CTYPES_PASS_BY_REF_HACK
ff4d630
+        size_t size = atypes[i]->size;
ff4d630
+        if (IS_PASS_BY_REF(size)) {
ff4d630
+            void *tmp = alloca(size);
ff4d630
+            if (atypes[i]->type == FFI_TYPE_STRUCT)
ff4d630
+                memcpy(tmp, args[i].value.p, size);
ff4d630
+            else
ff4d630
+                memcpy(tmp, (void*)&args[i].value, size);
ff4d630
+
ff4d630
+            avalues[i] = tmp;
ff4d630
+        }
ff4d630
+        else
ff4d630
+#endif
ff4d630
+        if (atypes[i]->type == FFI_TYPE_STRUCT)
ff4d630
             avalues[i] = (void *)args[i].value.p;
ff4d630
         else
ff4d630
             avalues[i] = (void *)&args[i].value;