Browse Source

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.
Ryan C. Gordon 1 year ago
parent
commit
25024ea295
2 changed files with 22 additions and 16 deletions
  1. 11 8
      src/core/gdk/SDL_gdk.cpp
  2. 11 8
      src/core/windows/SDL_windows.c

+ 11 - 8
src/core/gdk/SDL_gdk.cpp

@@ -108,18 +108,21 @@ int SDL_RunApp(int, char**, SDL_main_func mainFunction, void *reserved)
         return OutOfMemory();
         return OutOfMemory();
     }
     }
     for (i = 0; i < argc; ++i) {
     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]) {
         if (!argv[i]) {
             return OutOfMemory();
             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;
     argv[i] = NULL;
     LocalFree(argvw);
     LocalFree(argvw);

+ 11 - 8
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();
         return OutOfMemory();
     }
     }
     for (i = 0; i < argc; ++i) {
     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]) {
         if (!argv[i]) {
             return OutOfMemory();
             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;
     argv[i] = NULL;
     LocalFree(argvw);
     LocalFree(argvw);