SDL: windows: Before SDL_main has run, use WideCharToMultibyte, not SDL_iconv.

From 25024ea295b228edb897b243a671d7dad25a0986 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Wed, 22 May 2024 17:32:17 -0400
Subject: [PATCH] windows: Before SDL_main has run, use WideCharToMultibyte,
 not SDL_iconv.

Otherwise, this will crash if the app sets its own SDL_malloc allocator, since
SDL_iconv uses SDL_malloc.

WideCharToMultibyte lets us calculate the needed memory for the argv[] string
conversions, and then we use the win32 HeapAlloc() API to get some memory
for it.

Fixes #8967.
---
 src/core/gdk/SDL_gdk.cpp       | 19 +++++++++++--------
 src/core/windows/SDL_windows.c | 19 +++++++++++--------
 2 files changed, 22 insertions(+), 16 deletions(-)

diff --git a/src/core/gdk/SDL_gdk.cpp b/src/core/gdk/SDL_gdk.cpp
index 91d721745188f..8e7a8caaa4919 100644
--- a/src/core/gdk/SDL_gdk.cpp
+++ b/src/core/gdk/SDL_gdk.cpp
@@ -108,18 +108,21 @@ int SDL_RunApp(int, char**, SDL_main_func mainFunction, void *reserved)
         return OutOfMemory();
     }
     for (i = 0; i < argc; ++i) {
-        DWORD len;
-        char *arg = WIN_StringToUTF8W(argvw[i]);
-        if (arg == NULL) {
-            return OutOfMemory();
+        const int utf8size = WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
+        if (!utf8size) {  // uhoh?
+            SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
+            return -1;
         }
-        len = (DWORD)SDL_strlen(arg);
-        argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 1);
+
+        argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, utf8size);  // this size includes the null-terminator character.
         if (!argv[i]) {
             return OutOfMemory();
         }
-        SDL_memcpy(argv[i], arg, len);
-        SDL_free(arg);
+
+        if (WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, argv[i], utf8size, NULL, NULL) == 0) {  // failed? uhoh!
+            SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
+            return -1;
+        }
     }
     argv[i] = NULL;
     LocalFree(argvw);
diff --git a/src/core/windows/SDL_windows.c b/src/core/windows/SDL_windows.c
index b216706072024..eea88ff8e6bce 100644
--- a/src/core/windows/SDL_windows.c
+++ b/src/core/windows/SDL_windows.c
@@ -431,18 +431,21 @@ int MINGW32_FORCEALIGN SDL_RunApp(int _argc, char* _argv[], SDL_main_func mainFu
         return OutOfMemory();
     }
     for (i = 0; i < argc; ++i) {
-        DWORD len;
-        char *arg = WIN_StringToUTF8W(argvw[i]);
-        if (!arg) {
-            return OutOfMemory();
+        const int utf8size = WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, NULL, 0, NULL, NULL);
+        if (!utf8size) {  // uhoh?
+            SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
+            return -1;
         }
-        len = (DWORD)SDL_strlen(arg);
-        argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 1);
+
+        argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, utf8size);  // this size includes the null-terminator character.
         if (!argv[i]) {
             return OutOfMemory();
         }
-        SDL_memcpy(argv[i], arg, len);
-        SDL_free(arg);
+
+        if (WideCharToMultiByte(CP_UTF8, 0, argvw[i], -1, argv[i], utf8size, NULL, NULL) == 0) {  // failed? uhoh!
+            SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal Error", "Error processing command line arguments", NULL);
+            return -1;
+        }
     }
     argv[i] = NULL;
     LocalFree(argvw);