SDL: Unaligned stacks on i686-w64-mingw32, may lead to crashes (#7607)

From 8231278817faabdff4a232770f798684bd2e12df Mon Sep 17 00:00:00 2001
From: Christopher Wellons <[EMAIL REDACTED]>
Date: Sun, 9 Jul 2023 20:05:32 -0400
Subject: [PATCH] Unaligned stacks on i686-w64-mingw32, may lead to crashes
 (#7607)

Co-authored-by: Ozkan Sezer <sezeroz@gmail.com>
---
 CMakeLists.txt                      |  5 ----
 configure                           | 38 -----------------------------
 configure.ac                        | 23 -----------------
 src/SDL.c                           |  4 +--
 src/core/windows/SDL_windows.h      | 13 ++++++++++
 src/main/windows/SDL_windows_main.c |  2 +-
 src/thread/windows/SDL_systhread.c  |  4 +--
 7 files changed, 18 insertions(+), 71 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index d480e62aa651..1b073eb14119 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -620,11 +620,6 @@ if(USE_GCC OR USE_CLANG OR USE_INTELCC)
     endif()
   endif()
 
-  set(CMAKE_REQUIRED_FLAGS "-mpreferred-stack-boundary=2")
-  check_c_source_compiles("int x = 0; int main(int argc, char **argv) { return 0; }"
-    HAVE_GCC_PREFERRED_STACK_BOUNDARY)
-  set(CMAKE_REQUIRED_FLAGS ${ORIG_CMAKE_REQUIRED_FLAGS})
-
   set(CMAKE_REQUIRED_FLAGS "-fvisibility=hidden -Werror")
   check_c_source_compiles("
       #if !defined(__GNUC__) || __GNUC__ < 4
diff --git a/configure b/configure
index 85436935f32f..b107f6a95ad3 100755
--- a/configure
+++ b/configure
@@ -23026,41 +23026,6 @@ printf "%s\n" "$have_gcc_no_strict_aliasing" >&6; }
     fi
 }
 
-CheckStackBoundary()
-{
-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for GCC -mpreferred-stack-boundary option" >&5
-printf %s "checking for GCC -mpreferred-stack-boundary option... " >&6; }
-    have_gcc_preferred_stack_boundary=no
-
-    save_CFLAGS="$CFLAGS"
-    CFLAGS="$save_CFLAGS -mpreferred-stack-boundary=2"
-    cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h.  */
-
-    int x = 0;
-
-int
-main (void)
-{
-
-  ;
-  return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"
-then :
-  have_gcc_preferred_stack_boundary=yes
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
-    { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_gcc_preferred_stack_boundary" >&5
-printf "%s\n" "$have_gcc_preferred_stack_boundary" >&6; }
-    CFLAGS="$save_CFLAGS"
-
-    if test x$have_gcc_preferred_stack_boundary = xyes; then
-        EXTRA_CFLAGS="$EXTRA_CFLAGS -mpreferred-stack-boundary=2"
-    fi
-}
-
 CheckWerror()
 {
     # Check whether --enable-werror was given.
@@ -27474,9 +27439,6 @@ rm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext
     { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $have_wince" >&5
 printf "%s\n" "$have_wince" >&6; }
 
-    # This fixes Windows stack alignment with newer GCC
-    CheckStackBoundary
-
     # headers needed elsewhere
     ac_fn_c_check_header_compile "$LINENO" "tpcshrd.h" "ac_cv_header_tpcshrd_h" "$ac_includes_default"
 if test "x$ac_cv_header_tpcshrd_h" = xyes
diff --git a/configure.ac b/configure.ac
index 432b15208dbb..d3d0a07f0319 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1558,26 +1558,6 @@ CheckNoStrictAliasing()
     fi
 }
 
-dnl See if GCC's -mpreferred-stack-boundary is supported.
-dnl  Reference: http://bugzilla.libsdl.org/show_bug.cgi?id=1296
-CheckStackBoundary()
-{
-    AC_MSG_CHECKING(for GCC -mpreferred-stack-boundary option)
-    have_gcc_preferred_stack_boundary=no
-
-    save_CFLAGS="$CFLAGS"
-    CFLAGS="$save_CFLAGS -mpreferred-stack-boundary=2"
-    AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
-    int x = 0;
-    ]],[])], [have_gcc_preferred_stack_boundary=yes],[])
-    AC_MSG_RESULT($have_gcc_preferred_stack_boundary)
-    CFLAGS="$save_CFLAGS"
-
-    if test x$have_gcc_preferred_stack_boundary = xyes; then
-        EXTRA_CFLAGS="$EXTRA_CFLAGS -mpreferred-stack-boundary=2"
-    fi
-}
-
 dnl See if GCC's -Werror is supported.
 CheckWerror()
 {
@@ -3306,9 +3286,6 @@ CheckWINDOWS()
     ],[])
     AC_MSG_RESULT($have_wince)
 
-    # This fixes Windows stack alignment with newer GCC
-    CheckStackBoundary
-
     # headers needed elsewhere
     AC_CHECK_HEADER(tpcshrd.h,have_tpcshrd_h=yes)
     if test x$have_tpcshrd_h = xyes; then
diff --git a/src/SDL.c b/src/SDL.c
index 1be811151059..56049adf0ba5 100644
--- a/src/SDL.c
+++ b/src/SDL.c
@@ -631,9 +631,9 @@ SDL_bool SDL_IsTablet(void)
 #if defined(__WIN32__)
 
 #if (!defined(HAVE_LIBC) || defined(__WATCOMC__)) && !defined(SDL_STATIC_LIB)
-/* Need to include DllMain() on Watcom C for some reason.. */
+/* FIXME: Still need to include DllMain() on Watcom C ? */
 
-BOOL APIENTRY _DllMainCRTStartup(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
+BOOL APIENTRY MINGW32_FORCEALIGN _DllMainCRTStartup(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
 {
     switch (ul_reason_for_call) {
     case DLL_PROCESS_ATTACH:
diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h
index ac6def6341f1..3842e082b422 100644
--- a/src/core/windows/SDL_windows.h
+++ b/src/core/windows/SDL_windows.h
@@ -76,6 +76,19 @@
 #define WINVER       _WIN32_WINNT
 #endif
 
+/* See https://github.com/libsdl-org/SDL/pull/7607  */
+/* force_align_arg_pointer attribute requires gcc >= 4.2.x.  */
+#if defined(__clang__)
+#define HAVE_FORCE_ALIGN_ARG_POINTER
+#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2))
+#define HAVE_FORCE_ALIGN_ARG_POINTER
+#endif
+#if defined(__GNUC__) && defined(__i386__) && defined(HAVE_FORCE_ALIGN_ARG_POINTER)
+#define MINGW32_FORCEALIGN __attribute__((force_align_arg_pointer))
+#else
+#define MINGW32_FORCEALIGN
+#endif
+
 #include <windows.h>
 #include <basetyps.h> /* for REFIID with broken mingw.org headers */
 
diff --git a/src/main/windows/SDL_windows_main.c b/src/main/windows/SDL_windows_main.c
index e2725edd14ec..189b954202d8 100644
--- a/src/main/windows/SDL_windows_main.c
+++ b/src/main/windows/SDL_windows_main.c
@@ -103,7 +103,7 @@ int console_wmain(int argc, wchar_t *wargv[], wchar_t *wenvp)
 #endif
 
 /* This is where execution begins [windowed apps] */
-int WINAPI
+int WINAPI MINGW32_FORCEALIGN
 WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) /* NOLINT(readability-inconsistent-declaration-parameter-name) */
 {
     return main_getcmdline();
diff --git a/src/thread/windows/SDL_systhread.c b/src/thread/windows/SDL_systhread.c
index 1691469c87c8..b55eb132669c 100644
--- a/src/thread/windows/SDL_systhread.c
+++ b/src/thread/windows/SDL_systhread.c
@@ -55,12 +55,12 @@ static DWORD RunThread(void *data)
     return 0;
 }
 
-static DWORD WINAPI RunThreadViaCreateThread(LPVOID data)
+static DWORD WINAPI MINGW32_FORCEALIGN RunThreadViaCreateThread(LPVOID data)
 {
     return RunThread(data);
 }
 
-static unsigned __stdcall RunThreadViaBeginThreadEx(void *data)
+static unsigned __stdcall MINGW32_FORCEALIGN RunThreadViaBeginThreadEx(void *data)
 {
     return (unsigned)RunThread(data);
 }