- 
                Notifications
    You must be signed in to change notification settings 
- Fork 2.4k
Open
Description
Hi, currently it seems like SDL_GlobStorageDirectory is broken when used with a SDL_Storage created with SDL_OpenFileStorage(NULL).
SDL_OpenFileStorage constructs a new file storage with an optional base path, passing null is explicitly allowed:
SDL/include/SDL3/SDL_storage.h
Lines 388 to 389 in 9f721e8
| * \param path the base path prepended to all storage paths, or NULL for no | |
| * base path. | 
SDL_GlobStorageDirectory is used to search through a given storage, and as far as I can tell is not restricted from being called on such a storage object. However, currently it unconditionally assumes base_path is non-null, leading to a segmentation fault if that is violated.
Tested on c39d772a
(found via automated fuzzing)
The following testcase demonstrates the issue:
testcase.cpp
#include <SDL3/SDL.h>
#include <SDL3/SDL_storage.h>
int main() {
    // Open storage with a NULL base path (explicitly allowed by the API docs).
    SDL_Storage *st = SDL_OpenFileStorage(NULL);
    if (!st) return 0; // backend unavailable => exit cleanly
    // Storage is usually immediately ready in the generic backend.
    for (int i = 0; i < 3 && !SDL_StorageReady(st); i++) {}
    if (!SDL_StorageReady(st)) return 0;
    // Trigger enumeration; any simple relative path string suffices.
    int count = 0;
    char **list = SDL_GlobStorageDirectory(st, "test", NULL, 0, &count);
    if (list) SDL_free(list);
    return 0;
}crash report
{
  "Date": "2025-09-27T01:22:42.775429+00:00",
  "Uname": "Linux 90f16fa39b0b 5.15.0-140-generic #150-Ubuntu SMP Sat Apr 12 06:00:09 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux",
  "OS": "Ubuntu",
  "OSRelease": "22.04",
  "Architecture": "amd64",
  "ExecutablePath": "/tmp/tmp3ahg4kxq/reproducer",
  "ProcEnviron": [
    "LIBAFL_EDGES_MAP_SIZE=800000",
    "PWD=/fuzz/workspace",
    "GRAPHFUZZ_USE_ASAN=1",
    "HOME=/root",
    "ASAN_OPTIONS=hard_rss_limit_mb=1024:detect_leaks=0",
    "TERM=xterm-256color",
    "SHLVL=1",
    "LD_LIBRARY_PATH=/fuzz/install/lib",
    "PATH=/root/.cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "DEBIAN_FRONTEND=noninteractive",
    "OLDPWD=/fuzz/src",
    "_=/usr/local/bin/agfi"
  ],
  "ProcCmdline": "/tmp/tmp3ahg4kxq/reproducer",
  "Stdin": "",
  "ProcStatus": [],
  "ProcMaps": [],
  "ProcFiles": [],
  "NetworkConnections": [],
  "CrashSeverity": {
    "Type": "NOT_EXPLOITABLE",
    "ShortDescription": "SourceAvNearNull",
    "Description": "Access violation near NULL on source operand",
    "Explanation": "The target crashed on an access violation at an address matching the source operand of the current instruction. This likely indicates a read access violation, which may mean the application crashed on a simple NULL dereference to data structure that has no immediate effect on control of the processor."
  },
  "Stacktrace": [
    "    #0 0x7ffff7bf60bc  string/../sysdeps/x86_64/multiarch/strlen-evex.S:77",
    "    #1 0x5555555f77fa in strlen (/tmp/tmp3ahg4kxq/reproducer+0xa37fa) (BuildId: 2de8c80dfdceb67bec1fba978f75ecbbe15ea7ea)",
    "    #2 0x555555906bb0 in GENERIC_EnumerateStorageDirectory /fuzz/src/src/storage/generic/SDL_genericstorage.c:82:30",
    "    #3 0x55555570a886 in SDL_InternalGlobDirectory /fuzz/src/src/filesystem/SDL_filesystem.c:432:9",
    "    #4 0x5555557f20c1 in SDL_GlobStorageDirectory_REAL /fuzz/src/src/storage/SDL_storage.c:440:12",
    "    #5 0x5555556bccb3 in main /tmp/tmp3ahg4kxq/reproducer.cpp:15:19",
    "    #6 0x7ffff7a6dd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16",
    "    #7 0x7ffff7a6de3f in __libc_start_main csu/../csu/libc-start.c:392:3",
    "    #8 0x5555555e1a04 in _start (/tmp/tmp3ahg4kxq/reproducer+0x8da04) (BuildId: 2de8c80dfdceb67bec1fba978f75ecbbe15ea7ea)"
  ],
  "Registers": {},
  "Disassembly": [],
  "Package": "",
  "PackageVersion": "",
  "PackageArchitecture": "",
  "PackageDescription": "",
  "AsanReport": [
    "==155==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000000 (pc 0x7ffff7bf60bc bp 0x7fffffffe8d0 sp 0x7fffffffe088 T0)",
    "==155==The signal is caused by a READ memory access.",
    "==155==Hint: address points to the zero page.",
    "    #0 0x7ffff7bf60bc  string/../sysdeps/x86_64/multiarch/strlen-evex.S:77",
    "    #1 0x5555555f77fa in strlen (/tmp/tmp3ahg4kxq/reproducer+0xa37fa) (BuildId: 2de8c80dfdceb67bec1fba978f75ecbbe15ea7ea)",
    "    #2 0x555555906bb0 in GENERIC_EnumerateStorageDirectory /fuzz/src/src/storage/generic/SDL_genericstorage.c:82:30",
    "    #3 0x55555570a886 in SDL_InternalGlobDirectory /fuzz/src/src/filesystem/SDL_filesystem.c:432:9",
    "    #4 0x5555557f20c1 in SDL_GlobStorageDirectory_REAL /fuzz/src/src/storage/SDL_storage.c:440:12",
    "    #5 0x5555556bccb3 in main /tmp/tmp3ahg4kxq/reproducer.cpp:15:19",
    "    #6 0x7ffff7a6dd8f in __libc_start_call_main csu/../sysdeps/nptl/libc_start_call_main.h:58:16",
    "    #7 0x7ffff7a6de3f in __libc_start_main csu/../csu/libc-start.c:392:3",
    "    #8 0x5555555e1a04 in _start (/tmp/tmp3ahg4kxq/reproducer+0x8da04) (BuildId: 2de8c80dfdceb67bec1fba978f75ecbbe15ea7ea)",
    "",
    "AddressSanitizer can not provide additional info.",
    "SUMMARY: AddressSanitizer: SEGV string/../sysdeps/x86_64/multiarch/strlen-evex.S:77",
    "==155==ABORTING"
  ],
  "MsanReport": [],
  "UbsanReport": [],
  "LuaReport": [],
  "PythonReport": [],
  "GoReport": [],
  "JavaReport": [],
  "RustReport": [],
  "JsReport": [],
  "CSharpReport": [],
  "CrashLine": "/fuzz/src/src/storage/generic/SDL_genericstorage.c:82:30",
  "Source": [
    "    78         GenericEnumerateData wrap_data;",
    "    79     ",
    "    80         char *fullpath = GENERIC_INTERNAL_CreateFullPath((char *)userdata, path);",
    "    81         if (fullpath) {",
    "--->82             wrap_data.base_len = SDL_strlen((char *)userdata);",
    "    83             wrap_data.real_callback = callback;",
    "    84             wrap_data.real_userdata = callback_userdata;",
    "    85     ",
    "    86             result = SDL_EnumerateDirectory(fullpath, GENERIC_EnumerateDirectory, &wrap_data);",
    "    87     "
  ]
}Metadata
Metadata
Assignees
Labels
No labels