Skip to content

NULL base path in SDL_GlobStorageDirectory via SDL_OpenFileStorage(NULL) leads to NULL deref in GENERIC_EnumerateStorageDirectory #14060

@hgarrereyn

Description

@hgarrereyn

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:

* \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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions