Commit f88add14e40de398706c732e578620e8106062c7

Ole André Vadla Ravnås 2021-03-24T12:04:51

x86: Fix MSVC runtime checks interop (#612) MSVC can add runtime code that checks if a stack frame is mismanaged, however our custom assembly deliberately accesses and modifies the parent stack frame. Fortunately we can disable that specific check for the function call so do that. Co-authored-by: Matthew Waters <matthew@centricular.com>

diff --git a/src/x86/ffi.c b/src/x86/ffi.c
index b4d0d39..26dbc05 100644
--- a/src/x86/ffi.c
+++ b/src/x86/ffi.c
@@ -256,6 +256,13 @@ static const struct abi_params abi_params[FFI_LAST_ABI] = {
 
 extern void FFI_DECLARE_FASTCALL ffi_call_i386(struct call_frame *, char *) FFI_HIDDEN;
 
+/* We perform some black magic here to use some of the parent's stack frame in
+ * ffi_call_i386() that breaks with the MSVC compiler with the /RTCs or /GZ
+ * flags.  Disable the 'Stack frame run time error checking' for this function
+ * so we don't hit weird exceptions in debug builds. */
+#if defined(_MSC_VER)
+#pragma runtime_checks("s", off)
+#endif
 static void
 ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
 	      void **avalue, void *closure)
@@ -391,6 +398,9 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
 
   ffi_call_i386 (frame, stack);
 }
+#if defined(_MSC_VER)
+#pragma runtime_checks("s", restore)
+#endif
 
 void
 ffi_call (ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)
diff --git a/src/x86/ffiw64.c b/src/x86/ffiw64.c
index 6c28d59..6870d07 100644
--- a/src/x86/ffiw64.c
+++ b/src/x86/ffiw64.c
@@ -108,6 +108,13 @@ EFI64(ffi_prep_cif_machdep)(ffi_cif *cif)
   return FFI_OK;
 }
 
+/* We perform some black magic here to use some of the parent's stack frame in
+ * ffi_call_win64() that breaks with the MSVC compiler with the /RTCs or /GZ
+ * flags.  Disable the 'Stack frame run time error checking' for this function
+ * so we don't hit weird exceptions in debug builds. */
+#if defined(_MSC_VER)
+#pragma runtime_checks("s", off)
+#endif
 static void
 ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
 	      void **avalue, void *closure)
@@ -172,6 +179,9 @@ ffi_call_int (ffi_cif *cif, void (*fn)(void), void *rvalue,
 
   ffi_call_win64 (stack, frame, closure);
 }
+#if defined(_MSC_VER)
+#pragma runtime_checks("s", restore)
+#endif
 
 void
 EFI64(ffi_call)(ffi_cif *cif, void (*fn)(void), void *rvalue, void **avalue)