SDL: Unaligned stacks on i686-w64-mingw32 may lead to crashes

From 77446e20297a8d96b23506cf83d5273171ac7917 Mon Sep 17 00:00:00 2001
From: Ozkan Sezer <[EMAIL REDACTED]>
Date: Fri, 4 Aug 2023 10:23:20 +0300
Subject: [PATCH] Unaligned stacks on i686-w64-mingw32 may lead to crashes

Port of original SDL2 patch by Christopher Wellons (@skeeto, #7607)
to SDL3.
---
 src/SDL.c                          |  4 ++--
 src/core/SDL_runapp.c              |  9 ++++++++-
 src/core/windows/SDL_windows.h     | 13 +++++++++++++
 src/thread/windows/SDL_systhread.c |  4 ++--
 4 files changed, 25 insertions(+), 5 deletions(-)

diff --git a/src/SDL.c b/src/SDL.c
index e0381f9fd445..f099b04826e8 100644
--- a/src/SDL.c
+++ b/src/SDL.c
@@ -632,9 +632,9 @@ SDL_bool SDL_IsTablet(void)
 #ifdef __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/SDL_runapp.c b/src/core/SDL_runapp.c
index 02e25c6948f0..2a507b30e2bd 100644
--- a/src/core/SDL_runapp.c
+++ b/src/core/SDL_runapp.c
@@ -24,7 +24,14 @@
  * If not, you can special case it here by appending || defined(__YOUR_PLATFORM__) */
 #if ( !defined(SDL_MAIN_NEEDED) && !defined(SDL_MAIN_AVAILABLE) ) || defined(__ANDROID__)
 
-DECLSPEC int
+#if defined(__WIN32__) || defined(__WINRT__) || defined(__GDK__)
+#include "windows/SDL_windows.h"
+#endif
+#ifndef MINGW32_FORCEALIGN
+#define MINGW32_FORCEALIGN
+#endif
+
+DECLSPEC int MINGW32_FORCEALIGN
 SDL_RunApp(int argc, char* argv[], SDL_main_func mainFunction, void * reserved)
 {
     char empty[1] = {0};
diff --git a/src/core/windows/SDL_windows.h b/src/core/windows/SDL_windows.h
index e9eb1f0d6e4e..8928938342d3 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 */
 #include <mmreg.h>
diff --git a/src/thread/windows/SDL_systhread.c b/src/thread/windows/SDL_systhread.c
index f111c627a726..8755f67c3833 100644
--- a/src/thread/windows/SDL_systhread.c
+++ b/src/thread/windows/SDL_systhread.c
@@ -53,12 +53,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);
 }