Commit f1ad942a1175105e4ab7d1cd98b842f84b3bcb2b

Steven Noonan 2021-04-22T17:24:05

SDL_windows_main: use HeapAlloc/HeapFree for command line arguments If a developer uses SDL_SetMemoryFunctions, we can't rely on SDL_free() working when SDL_main() returns. Signed-off-by: Steven Noonan <steven@valvesoftware.com> Signed-off-by: Sam Lantinga <slouken@libsdl.org>

diff --git a/src/main/windows/SDL_windows_main.c b/src/main/windows/SDL_windows_main.c
index 6333f2c..056787e 100644
--- a/src/main/windows/SDL_windows_main.c
+++ b/src/main/windows/SDL_windows_main.c
@@ -49,16 +49,29 @@ main_getcmdline(void)
         return OutOfMemory();
     }
 
+    /* Note that we need to be careful about how we allocate/free memory here.
+     * If the application calls SDL_SetMemoryFunctions(), we can't rely on
+     * SDL_free() to use the same allocator after SDL_main() returns.
+     */
+
     /* Parse it into argv and argc */
-    argv = (char **)SDL_calloc(argc + 1, sizeof(*argv));
+    argv = (char **)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (argc + 1) * sizeof(*argv));
     if (!argv) {
         return OutOfMemory();
     }
     for (i = 0; i < argc; ++i) {
-        argv[i] = WIN_StringToUTF8W(argvw[i]);
+        DWORD len;
+        char *arg = WIN_StringToUTF8W(argvw[i]);
+        if (!arg) {
+            return OutOfMemory();
+        }
+        len = (DWORD)SDL_strlen(arg);
+        argv[i] = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len + 1);
         if (!argv[i]) {
             return OutOfMemory();
         }
+        CopyMemory(argv[i], arg, len);
+        SDL_free(arg);
     }
     argv[i] = NULL;
     LocalFree(argvw);
@@ -70,9 +83,9 @@ main_getcmdline(void)
 
     /* Free argv, to avoid memory leak */
     for (i = 0; i < argc; ++i) {
-        SDL_free(argv[i]);
+        HeapFree(GetProcessHeap(), 0, argv[i]);
     }
-    SDL_free(argv);
+    HeapFree(GetProcessHeap(), 0, argv);
 
     return result;
 }