SDL: Make SDL_GetTrayEntires() NULL-terminated

From 7673b84f52605e532e5f312cf319cb5fca4e0c2a Mon Sep 17 00:00:00 2001
From: Semphris <[EMAIL REDACTED]>
Date: Sat, 4 Jan 2025 13:33:19 -0500
Subject: [PATCH] Make SDL_GetTrayEntires() NULL-terminated

---
 include/SDL3/SDL_tray.h     | 6 +++---
 src/tray/cocoa/SDL_tray.m   | 6 ++++--
 src/tray/unix/SDL_tray.c    | 6 ++++--
 src/tray/windows/SDL_tray.c | 6 ++++--
 4 files changed, 15 insertions(+), 9 deletions(-)

diff --git a/include/SDL3/SDL_tray.h b/include/SDL3/SDL_tray.h
index 01d6bf30f91bc..99fbcb0e20ba0 100644
--- a/include/SDL3/SDL_tray.h
+++ b/include/SDL3/SDL_tray.h
@@ -228,9 +228,9 @@ extern SDL_DECLSPEC SDL_TrayMenu *SDLCALL SDL_GetTraySubmenu(SDL_TrayEntry *entr
  * \param menu The menu to get entries from.
  * \param size An optional pointer to obtain the number of entries in the
  *             menu.
- * \returns the entries within the given menu. The pointer becomes invalid
- *          when any function that inserts or deletes entries in the menu is
- *          called.
+ * \returns a NULL-terminated list of entries within the given menu. The pointer
+ *          becomes invalid when any function that inserts or deletes entries in
+ *          the menu is called.
  *
  * \since This function is available since SDL 3.2.0.
  *
diff --git a/src/tray/cocoa/SDL_tray.m b/src/tray/cocoa/SDL_tray.m
index 20407b9762e9d..8cb0619314c5e 100644
--- a/src/tray/cocoa/SDL_tray.m
+++ b/src/tray/cocoa/SDL_tray.m
@@ -309,11 +309,12 @@ void SDL_RemoveTrayEntry(SDL_TrayEntry *entry)
     }
 
     menu->nEntries--;
-    SDL_TrayEntry **new_entries = (SDL_TrayEntry **)SDL_realloc(menu->entries, menu->nEntries * sizeof(*new_entries));
+    SDL_TrayEntry **new_entries = (SDL_TrayEntry **)SDL_realloc(menu->entries, (menu->nEntries + 1) * sizeof(*new_entries));
 
     /* Not sure why shrinking would fail, but even if it does, we can live with a "too big" array */
     if (new_entries) {
         menu->entries = new_entries;
+        menu->entries[menu->nEntries] = NULL;
     }
 
     [menu->nsmenu removeItem:entry->nsitem];
@@ -337,7 +338,7 @@ void SDL_RemoveTrayEntry(SDL_TrayEntry *entry)
         return NULL;
     }
 
-    SDL_TrayEntry **new_entries = (SDL_TrayEntry **)SDL_realloc(menu->entries, (menu->nEntries + 1) * sizeof(*new_entries));
+    SDL_TrayEntry **new_entries = (SDL_TrayEntry **)SDL_realloc(menu->entries, (menu->nEntries + 2) * sizeof(*new_entries));
     if (!new_entries) {
         SDL_free(entry);
         return NULL;
@@ -351,6 +352,7 @@ void SDL_RemoveTrayEntry(SDL_TrayEntry *entry)
     }
 
     new_entries[pos] = entry;
+    new_entries[menu->nEntries] = NULL;
 
     NSMenuItem *nsitem;
     if (label == NULL) {
diff --git a/src/tray/unix/SDL_tray.c b/src/tray/unix/SDL_tray.c
index 1219fa6d4ba12..994fb5de95756 100644
--- a/src/tray/unix/SDL_tray.c
+++ b/src/tray/unix/SDL_tray.c
@@ -518,11 +518,12 @@ void SDL_RemoveTrayEntry(SDL_TrayEntry *entry)
     }
 
     menu->nEntries--;
-    SDL_TrayEntry ** new_entries = SDL_realloc(menu->entries, menu->nEntries * sizeof(SDL_TrayEntry *));
+    SDL_TrayEntry ** new_entries = SDL_realloc(menu->entries, (menu->nEntries + 1) * sizeof(SDL_TrayEntry *));
 
     /* Not sure why shrinking would fail, but even if it does, we can live with a "too big" array */
     if (new_entries) {
         menu->entries = new_entries;
+        menu->entries[menu->nEntries] = NULL;
     }
 
     gtk_widget_destroy(entry->item);
@@ -566,7 +567,7 @@ SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *la
 
     gtk_widget_set_sensitive(entry->item, !(flags & SDL_TRAYENTRY_DISABLED));
 
-    SDL_TrayEntry **new_entries = (SDL_TrayEntry **) SDL_realloc(menu->entries, (menu->nEntries + 1) * sizeof(SDL_TrayEntry *));
+    SDL_TrayEntry **new_entries = (SDL_TrayEntry **) SDL_realloc(menu->entries, (menu->nEntries + 2) * sizeof(SDL_TrayEntry *));
 
     if (!new_entries) {
         SDL_free(entry);
@@ -581,6 +582,7 @@ SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *la
     }
 
     new_entries[pos] = entry;
+    new_entries[menu->nEntries] = NULL;
 
     gtk_widget_show(entry->item);
     gtk_menu_shell_insert(menu->menu, entry->item, (pos == menu->nEntries) ? -1 : pos);
diff --git a/src/tray/windows/SDL_tray.c b/src/tray/windows/SDL_tray.c
index 545808cc0e9a1..125daa10ff6a5 100644
--- a/src/tray/windows/SDL_tray.c
+++ b/src/tray/windows/SDL_tray.c
@@ -330,11 +330,12 @@ void SDL_RemoveTrayEntry(SDL_TrayEntry *entry)
     }
 
     menu->nEntries--;
-    SDL_TrayEntry ** new_entries = SDL_realloc(menu->entries, menu->nEntries * sizeof(SDL_TrayEntry *));
+    SDL_TrayEntry ** new_entries = SDL_realloc(menu->entries, (menu->nEntries + 1) * sizeof(SDL_TrayEntry *));
 
     /* Not sure why shrinking would fail, but even if it does, we can live with a "too big" array */
     if (new_entries) {
         menu->entries = new_entries;
+        menu->entries[menu->nEntries] = NULL;
     }
 
     if (!DeleteMenu(menu->hMenu, (UINT) entry->id, MF_BYCOMMAND)) {
@@ -398,7 +399,7 @@ SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *la
         entry->id = get_next_id();
     }
 
-    SDL_TrayEntry **new_entries = (SDL_TrayEntry **) SDL_realloc(menu->entries, (menu->nEntries + 1) * sizeof(SDL_TrayEntry **));
+    SDL_TrayEntry **new_entries = (SDL_TrayEntry **) SDL_realloc(menu->entries, (menu->nEntries + 2) * sizeof(SDL_TrayEntry **));
 
     if (!new_entries) {
         SDL_free(entry);
@@ -418,6 +419,7 @@ SDL_TrayEntry *SDL_InsertTrayEntryAt(SDL_TrayMenu *menu, int pos, const char *la
     }
 
     new_entries[pos] = entry;
+    new_entries[menu->nEntries] = NULL;
 
     if (label == NULL) {
         InsertMenuW(menu->hMenu, windows_compatible_pos, MF_SEPARATOR | MF_BYPOSITION, entry->id, NULL);