SDL: Fix possible bug with Windows dialogs

From 684098fac35a526c8ead41c0d16cdbf5b048e364 Mon Sep 17 00:00:00 2001
From: Semphris <[EMAIL REDACTED]>
Date: Tue, 17 Dec 2024 23:03:42 -0500
Subject: [PATCH] Fix possible bug with Windows dialogs

The Windows implementation of dialogs use the Win32 API, which expects the file filters to have null bytes as separator, and two null bytes at the end of the filter list. To help with string manipulation, the internal code uses 0x01 bytes instead of null bytes, and converts all 0x01 bytes into null bytes at the last moment. If someone decides to put two consecutive 0x01 bytes in their filter names, the code might mistakenly pick them up and convert them to null bytes, leading to Windows failing to pick up later filters. In practice, this is probably not so bad, since it requires someone to have control over file filters already, and allows at most ignoring the following file filters. It is also unlikely to happen by accident since 0x01 is not printable. This commit fixes that by replacing all the 0x01 bytes with the space character.
---
 src/dialog/windows/SDL_windowsdialog.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/src/dialog/windows/SDL_windowsdialog.c b/src/dialog/windows/SDL_windowsdialog.c
index 067219dcd4ff1..eb1f35e8843c2 100644
--- a/src/dialog/windows/SDL_windowsdialog.c
+++ b/src/dialog/windows/SDL_windowsdialog.c
@@ -63,6 +63,24 @@ int getFilterIndex(int as_reported_by_windows)
     return as_reported_by_windows - 1;
 }
 
+char *clear_filt_names(const char *filt)
+{
+    char *cleared = SDL_strdup(filt);
+
+    for (char *c = cleared; *c; c++) {
+        /* 0x01 bytes are used as temporary replacement for the various 0x00
+           bytes required by Win32 (one null byte between each filter, two at
+           the end of the filters). Filter out these bytes from the filter names
+           to avoid early-ending the filters if someone puts two consecutive
+           0x01 bytes in their filter names. */
+        if (*c == '\x01') {
+            *c = ' ';
+        }
+    }
+
+    return cleared;
+}
+
 // TODO: The new version of file dialogs
 void windows_ShowFileDialog(void *ptr)
 {
@@ -161,7 +179,7 @@ void windows_ShowFileDialog(void *ptr)
     if (filters) {
         // '\x01' is used in place of a null byte
         // suffix needs two null bytes in case the filter list is empty
-        char *filterlist = convert_filters(filters, nfilters, NULL, "", "",
+        char *filterlist = convert_filters(filters, nfilters, clear_filt_names, "", "",
                                            "\x01\x01", "", "\x01", "\x01",
                                            "*.", ";*.", "");