From 7c181233272eb124fa5e2e33c81113239b7a2a75 Mon Sep 17 00:00:00 2001 From: Misa Date: Thu, 19 Aug 2021 00:23:51 -0700 Subject: [PATCH] Wrap level dir enumerate callback pointer in struct In order to let callers provide their OWN callback functions through the callback function WE provide to PhysFS, we casted the function pointer to a void pointer. Unfortunately, this is apparently undefined behavior... if your compiler doesn't have an extension for it. And most compilers on most architectures do. (In fact compilers on POSIX systems most certainly have it due to dlsym() returning a void* which could actually be a pointer to a function sometimes.) But imo, it's better to be safe than sorry in this regard. Especially when given GCC's approach to optimizing int + 100 > int (spoilers: they remove it entirely! It's faster, but also broken!). I've decided to wrap it in a struct. And as a nice side effect, if we ever need more data to be passed through... well we already have this struct. Technically, it's also standards-compliant to cast a _pointer to_ a function pointer to a void pointer. But that extra layer of pointer indirection would get real confusing to conceptualize real fast (or at least is more confusing than just putting it in a struct). --- desktop_version/src/FileSystemUtils.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/desktop_version/src/FileSystemUtils.cpp b/desktop_version/src/FileSystemUtils.cpp index 30706af5..833a3dea 100644 --- a/desktop_version/src/FileSystemUtils.cpp +++ b/desktop_version/src/FileSystemUtils.cpp @@ -896,12 +896,18 @@ bool FILESYSTEM_loadTiXml2Document(const char *name, tinyxml2::XMLDocument& doc) return true; } +struct CallbackWrapper +{ + void (*callback)(const char* filename); +}; + static PHYSFS_EnumerateCallbackResult enumerateCallback( void* data, const char* origdir, const char* filename ) { - void (*callback)(const char*) = (void (*)(const char*)) data; + struct CallbackWrapper* wrapper = (struct CallbackWrapper*) data; + void (*callback)(const char*) = wrapper->callback; char builtLocation[MAX_PATH]; SDL_snprintf( @@ -921,8 +927,9 @@ void FILESYSTEM_enumerateLevelDirFileNames( void (*callback)(const char* filename) ) { int success; + struct CallbackWrapper wrapper = {callback}; - success = PHYSFS_enumerate("levels", enumerateCallback, (void*) callback); + success = PHYSFS_enumerate("levels", enumerateCallback, (void*) &wrapper); if (success == 0) { @@ -1200,11 +1207,12 @@ static void levelSaveCallback(const char* filename) void FILESYSTEM_deleteLevelSaves(void) { int success; + struct CallbackWrapper wrapper = {levelSaveCallback}; success = PHYSFS_enumerate( "saves", enumerateCallback, - (void*) levelSaveCallback + (void*) &wrapper ); if (success == 0)