SDL: stdinc: SDL_SetMemoryFunctions now handles NULL function pointers better.

From eb04627741a04209c5ca47b5421f9c8961f58544 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Wed, 1 Jul 2026 14:59:55 -0400
Subject: [PATCH] stdinc: SDL_SetMemoryFunctions now handles NULL function
 pointers better.

Now it does _not_ call SDL_SetError(), since that would allocate memory with
the system in a weird state, and setting all four functions to NULL will
restore the original memory functions, as a shortcut vs having to query
SDL_GetOriginalMemoryFunctions() first.

Fixes #15914.
---
 include/SDL3/SDL_stdinc.h | 16 +++++++++++-----
 src/stdlib/SDL_malloc.c   | 25 +++++++++----------------
 2 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/include/SDL3/SDL_stdinc.h b/include/SDL3/SDL_stdinc.h
index 88794ce3e32a2..c8ad77e55574e 100644
--- a/include/SDL3/SDL_stdinc.h
+++ b/include/SDL3/SDL_stdinc.h
@@ -1573,12 +1573,18 @@ extern SDL_DECLSPEC void SDLCALL SDL_GetMemoryFunctions(SDL_malloc_func *malloc_
  * If used, usually this needs to be the first call made into the SDL library,
  * if not the very first thing done at program startup time.
  *
+ * It is legal to call this with all 4 parameters set to NULL, which will
+ * restore the original memory functions without having to query them with
+ * SDL_GetOriginalMemoryFunctions() first.
+ *
  * \param malloc_func custom malloc function.
  * \param calloc_func custom calloc function.
  * \param realloc_func custom realloc function.
  * \param free_func custom free function.
- * \returns true on success or false on failure; call SDL_GetError() for more
- *          information.
+ * \returns true on success or false on failure. This only fails if there is
+ *          a mix of NULL and non-NULL parameters. Failure will not set an
+ *          error message (which allocates memory) so do _not_ call
+ *          SDL_GetError() in response to a failure here.
  *
  * \threadsafety It is safe to call this function from any thread, but one
  *               should not replace the memory functions once any allocations
@@ -1590,9 +1596,9 @@ extern SDL_DECLSPEC void SDLCALL SDL_GetMemoryFunctions(SDL_malloc_func *malloc_
  * \sa SDL_GetOriginalMemoryFunctions
  */
 extern SDL_DECLSPEC bool SDLCALL SDL_SetMemoryFunctions(SDL_malloc_func malloc_func,
-                                                            SDL_calloc_func calloc_func,
-                                                            SDL_realloc_func realloc_func,
-                                                            SDL_free_func free_func);
+                                                        SDL_calloc_func calloc_func,
+                                                        SDL_realloc_func realloc_func,
+                                                        SDL_free_func free_func);
 
 /**
  * Allocate memory aligned to a specific alignment.
diff --git a/src/stdlib/SDL_malloc.c b/src/stdlib/SDL_malloc.c
index cd48c61d9faf6..3e7d0fdc9a7ee 100644
--- a/src/stdlib/SDL_malloc.c
+++ b/src/stdlib/SDL_malloc.c
@@ -6537,23 +6537,16 @@ bool SDL_SetMemoryFunctions(SDL_malloc_func malloc_func,
                                 SDL_realloc_func realloc_func,
                                 SDL_free_func free_func)
 {
-    CHECK_PARAM(!malloc_func) {
-        return SDL_InvalidParamError("malloc_func");
-    }
-    CHECK_PARAM(!calloc_func) {
-        return SDL_InvalidParamError("calloc_func");
-    }
-    CHECK_PARAM(!realloc_func) {
-        return SDL_InvalidParamError("realloc_func");
-    }
-    CHECK_PARAM(!free_func) {
-        return SDL_InvalidParamError("free_func");
+    if (!malloc_func && !calloc_func && !realloc_func && !free_func) {
+        SDL_GetOriginalMemoryFunctions(&s_mem.malloc_func, &s_mem.calloc_func, &s_mem.realloc_func, &s_mem.free_func);
+    } else if (!malloc_func || !calloc_func || !realloc_func || !free_func) {  // if not all are NULL, none of them can be NULL.
+        return false;  // do _not_ set an error message in here, since it will allocate memory!
+    } else {
+        s_mem.malloc_func = malloc_func;
+        s_mem.calloc_func = calloc_func;
+        s_mem.realloc_func = realloc_func;
+        s_mem.free_func = free_func;
     }
-
-    s_mem.malloc_func = malloc_func;
-    s_mem.calloc_func = calloc_func;
-    s_mem.realloc_func = realloc_func;
-    s_mem.free_func = free_func;
     return true;
 }