From af1c05fd58d67e3a3c3acbbdf7d9aea533ead697 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Tue, 22 Jul 2025 12:28:01 -0400
Subject: [PATCH] filesystem: Check SDL_GetPrefPath parameters at the higher
level.
...so the backends don't have to do it.
Also added a stern warning about `org` being omitted, but leaving it as
allowed so as not to break existing apps (more than they are already broken,
at least).
Fixes #13322.
---
include/SDL3/SDL_filesystem.h | 6 ++++++
src/filesystem/SDL_filesystem.c | 10 ++++++++++
src/filesystem/cocoa/SDL_sysfilesystem.m | 11 +----------
src/filesystem/emscripten/SDL_sysfilesystem.c | 12 +-----------
src/filesystem/gdk/SDL_sysfilesystem.cpp | 5 -----
src/filesystem/haiku/SDL_sysfilesystem.cc | 8 --------
src/filesystem/n3ds/SDL_sysfilesystem.c | 5 -----
src/filesystem/ps2/SDL_sysfilesystem.c | 10 ----------
src/filesystem/psp/SDL_sysfilesystem.c | 13 +------------
src/filesystem/riscos/SDL_sysfilesystem.c | 11 +----------
src/filesystem/unix/SDL_sysfilesystem.c | 11 +----------
src/filesystem/vita/SDL_sysfilesystem.c | 14 +-------------
src/filesystem/windows/SDL_sysfilesystem.c | 8 --------
13 files changed, 22 insertions(+), 102 deletions(-)
diff --git a/include/SDL3/SDL_filesystem.h b/include/SDL3/SDL_filesystem.h
index 031feaf98e533..e4282582185c3 100644
--- a/include/SDL3/SDL_filesystem.h
+++ b/include/SDL3/SDL_filesystem.h
@@ -134,6 +134,12 @@ extern SDL_DECLSPEC const char * SDLCALL SDL_GetBasePath(void);
* - ...only use letters, numbers, and spaces. Avoid punctuation like "Game
* Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient.
*
+ * Due to historical mistakes, `org` is allowed to be NULL or "". In such
+ * cases, SDL will omit the org subdirectory, including on platforms where it
+ * shouldn't, and including on platforms where this would make your app fail
+ * certification for an app store. New apps should definitely specify a real
+ * string for `org`.
+ *
* The returned path is guaranteed to end with a path separator ('\\' on
* Windows, '/' on most other platforms).
*
diff --git a/src/filesystem/SDL_filesystem.c b/src/filesystem/SDL_filesystem.c
index b115019ba5491..8bd7980aaacac 100644
--- a/src/filesystem/SDL_filesystem.c
+++ b/src/filesystem/SDL_filesystem.c
@@ -502,6 +502,16 @@ const char *SDL_GetUserFolder(SDL_Folder folder)
char *SDL_GetPrefPath(const char *org, const char *app)
{
+ if (!app) {
+ SDL_InvalidParamError("app");
+ return NULL;
+ }
+
+ // if org is NULL, just make it "" so backends don't have to check both.
+ if (!org) {
+ org = "";
+ }
+
return SDL_SYS_GetPrefPath(org, app);
}
diff --git a/src/filesystem/cocoa/SDL_sysfilesystem.m b/src/filesystem/cocoa/SDL_sysfilesystem.m
index 6ecef5dfc227c..d0b4ba9553dfd 100644
--- a/src/filesystem/cocoa/SDL_sysfilesystem.m
+++ b/src/filesystem/cocoa/SDL_sysfilesystem.m
@@ -69,14 +69,6 @@
char *result = NULL;
NSArray *array;
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
- if (!org) {
- org = "";
- }
-
#ifndef SDL_PLATFORM_TVOS
array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
#else
@@ -106,13 +98,12 @@
const size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;
result = (char *)SDL_malloc(len);
if (result != NULL) {
- char *ptr;
if (*org) {
SDL_snprintf(result, len, "%s/%s/%s/", base, org, app);
} else {
SDL_snprintf(result, len, "%s/%s/", base, app);
}
- for (ptr = result + 1; *ptr; ptr++) {
+ for (char *ptr = result + 1; *ptr; ptr++) {
if (*ptr == '/') {
*ptr = '\0';
mkdir(result, 0700);
diff --git a/src/filesystem/emscripten/SDL_sysfilesystem.c b/src/filesystem/emscripten/SDL_sysfilesystem.c
index 29dc053511829..afb9705b47b3d 100644
--- a/src/filesystem/emscripten/SDL_sysfilesystem.c
+++ b/src/filesystem/emscripten/SDL_sysfilesystem.c
@@ -42,17 +42,7 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
const char *append = "/libsdl/";
char *result;
char *ptr = NULL;
- size_t len = 0;
-
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
- if (!org) {
- org = "";
- }
-
- len = SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3;
+ const size_t len = SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3;
result = (char *)SDL_malloc(len);
if (!result) {
return NULL;
diff --git a/src/filesystem/gdk/SDL_sysfilesystem.cpp b/src/filesystem/gdk/SDL_sysfilesystem.cpp
index 9a97f1873bb52..17baafb7203b2 100644
--- a/src/filesystem/gdk/SDL_sysfilesystem.cpp
+++ b/src/filesystem/gdk/SDL_sysfilesystem.cpp
@@ -90,11 +90,6 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
HRESULT result;
const char *csid = SDL_GetHint("SDL_GDK_SERVICE_CONFIGURATION_ID");
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
-
// This should be set before calling SDL_GetPrefPath!
if (!csid) {
SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM, "Set SDL_GDK_SERVICE_CONFIGURATION_ID before calling SDL_GetPrefPath!");
diff --git a/src/filesystem/haiku/SDL_sysfilesystem.cc b/src/filesystem/haiku/SDL_sysfilesystem.cc
index af8b5ab4d3bc0..1c8a0acc4de7a 100644
--- a/src/filesystem/haiku/SDL_sysfilesystem.cc
+++ b/src/filesystem/haiku/SDL_sysfilesystem.cc
@@ -72,14 +72,6 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
const char *append = "/config/settings/";
size_t len = SDL_strlen(home);
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
- if (!org) {
- org = "";
- }
-
if (!len || (home[len - 1] == '/')) {
++append; // home empty or ends with separator, skip the one from append
}
diff --git a/src/filesystem/n3ds/SDL_sysfilesystem.c b/src/filesystem/n3ds/SDL_sysfilesystem.c
index 8386a91c5c7f9..36b8c23126d74 100644
--- a/src/filesystem/n3ds/SDL_sysfilesystem.c
+++ b/src/filesystem/n3ds/SDL_sysfilesystem.c
@@ -43,11 +43,6 @@ char *SDL_SYS_GetBasePath(void)
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
{
char *pref_path = NULL;
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
-
pref_path = MakePrefPath(app);
if (!pref_path) {
return NULL;
diff --git a/src/filesystem/ps2/SDL_sysfilesystem.c b/src/filesystem/ps2/SDL_sysfilesystem.c
index ca69c2bd0a8bb..8b4644e79ab01 100644
--- a/src/filesystem/ps2/SDL_sysfilesystem.c
+++ b/src/filesystem/ps2/SDL_sysfilesystem.c
@@ -80,15 +80,6 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
char *result = NULL;
size_t len;
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
-
- if (!org) {
- org = "";
- }
-
const char *base = SDL_GetBasePath();
if (!base) {
return NULL;
@@ -102,7 +93,6 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
} else {
SDL_snprintf(result, len, "%s%s/", base, app);
}
-
recursive_mkdir(result);
}
diff --git a/src/filesystem/psp/SDL_sysfilesystem.c b/src/filesystem/psp/SDL_sysfilesystem.c
index 4b40055b35d1b..eb9356a98861f 100644
--- a/src/filesystem/psp/SDL_sysfilesystem.c
+++ b/src/filesystem/psp/SDL_sysfilesystem.c
@@ -49,22 +49,12 @@ char *SDL_SYS_GetBasePath(void)
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
{
char *result = NULL;
- size_t len;
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
-
const char *base = SDL_GetBasePath();
if (!base) {
return NULL;
}
- if (!org) {
- org = "";
- }
-
- len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;
+ const size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;
result = (char *)SDL_malloc(len);
if (result) {
if (*org) {
@@ -72,7 +62,6 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
} else {
SDL_snprintf(result, len, "%s%s/", base, app);
}
-
mkdir(result, 0755);
}
diff --git a/src/filesystem/riscos/SDL_sysfilesystem.c b/src/filesystem/riscos/SDL_sysfilesystem.c
index 95ed80fda95d9..d394a6473bc58 100644
--- a/src/filesystem/riscos/SDL_sysfilesystem.c
+++ b/src/filesystem/riscos/SDL_sysfilesystem.c
@@ -155,23 +155,14 @@ char *SDL_SYS_GetBasePath(void)
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
{
char *canon, *dir, *result;
- size_t len;
_kernel_oserror *error;
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
- if (!org) {
- org = "";
- }
-
canon = canonicalisePath("<Choices$Write>", "Run$Path");
if (!canon) {
return NULL;
}
- len = SDL_strlen(canon) + SDL_strlen(org) + SDL_strlen(app) + 4;
+ const size_t len = SDL_strlen(canon) + SDL_strlen(org) + SDL_strlen(app) + 4;
dir = (char *)SDL_malloc(len);
if (!dir) {
SDL_free(canon);
diff --git a/src/filesystem/unix/SDL_sysfilesystem.c b/src/filesystem/unix/SDL_sysfilesystem.c
index 858aaa2c54cec..751cc8a45a9bb 100644
--- a/src/filesystem/unix/SDL_sysfilesystem.c
+++ b/src/filesystem/unix/SDL_sysfilesystem.c
@@ -269,15 +269,6 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
const char *append;
char *result = NULL;
char *ptr = NULL;
- size_t len = 0;
-
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
- if (!org) {
- org = "";
- }
if (!envr) {
// You end up with "$HOME/.local/share/Game Name 2"
@@ -292,7 +283,7 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
append = "/";
}
- len = SDL_strlen(envr);
+ size_t len = SDL_strlen(envr);
if (envr[len - 1] == '/') {
append += 1;
}
diff --git a/src/filesystem/vita/SDL_sysfilesystem.c b/src/filesystem/vita/SDL_sysfilesystem.c
index 8b65e8ae415d8..d99a83d125f69 100644
--- a/src/filesystem/vita/SDL_sysfilesystem.c
+++ b/src/filesystem/vita/SDL_sysfilesystem.c
@@ -46,19 +46,7 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
const char *envr = "ux0:/data/";
char *result = NULL;
char *ptr = NULL;
- size_t len = 0;
-
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
- if (!org) {
- org = "";
- }
-
- len = SDL_strlen(envr);
-
- len += SDL_strlen(org) + SDL_strlen(app) + 3;
+ size_t len = SDL_strlen(envr) + SDL_strlen(org) + SDL_strlen(app) + 3;
result = (char *)SDL_malloc(len);
if (!result) {
return NULL;
diff --git a/src/filesystem/windows/SDL_sysfilesystem.c b/src/filesystem/windows/SDL_sysfilesystem.c
index a4c033f068a03..85bf1ceb9693e 100644
--- a/src/filesystem/windows/SDL_sysfilesystem.c
+++ b/src/filesystem/windows/SDL_sysfilesystem.c
@@ -110,14 +110,6 @@ char *SDL_SYS_GetPrefPath(const char *org, const char *app)
size_t new_wpath_len = 0;
BOOL api_result = FALSE;
- if (!app) {
- SDL_InvalidParamError("app");
- return NULL;
- }
- if (!org) {
- org = "";
- }
-
hr = SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path);
if (!SUCCEEDED(hr)) {
WIN_SetErrorFromHRESULT("Couldn't locate our prefpath", hr);