dynapi: don't let system loader resolve the initializer to the wrong version.
authorRyan C. Gordon <icculus@icculus.org>
Thu, 17 May 2018 12:50:46 -0400
changeset 119827babfecee045
parent 11981 9e46f3dd75fd
child 11983 3a50eb90e4b2
dynapi: don't let system loader resolve the initializer to the wrong version.

Fixes problems launching Firewatch on Linux (which statically links SDL but
also dynamically loads a system-wide copy from a plugin shared library) with
a newer SDL build.
src/dynapi/SDL_dynapi.c
     1.1 --- a/src/dynapi/SDL_dynapi.c	Fri May 11 09:37:00 2018 +0300
     1.2 +++ b/src/dynapi/SDL_dynapi.c	Thu May 17 12:50:46 2018 -0400
     1.3 @@ -167,15 +167,10 @@
     1.4  #error Write me.
     1.5  #endif
     1.6  
     1.7 -
     1.8 -
     1.9 -/* Here's the exported entry point that fills in the jump table. */
    1.10 -/*  Use specific types when an "int" might suffice to keep this sane. */
    1.11 -typedef Sint32 (SDLCALL *SDL_DYNAPI_ENTRYFN)(Uint32 apiver, void *table, Uint32 tablesize);
    1.12 -extern DECLSPEC Sint32 SDLCALL SDL_DYNAPI_entry(Uint32, void *, Uint32);
    1.13 -
    1.14 -Sint32
    1.15 -SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize)
    1.16 +/* we make this a static function so we can call the correct one without the
    1.17 +   system's dynamic linker resolving to the wrong version of this. */
    1.18 +static Sint32
    1.19 +initialize_jumptable(Uint32 apiver, void *table, Uint32 tablesize)
    1.20  {
    1.21      SDL_DYNAPI_jump_table *output_jump_table = (SDL_DYNAPI_jump_table *) table;
    1.22  
    1.23 @@ -202,6 +197,18 @@
    1.24  }
    1.25  
    1.26  
    1.27 +/* Here's the exported entry point that fills in the jump table. */
    1.28 +/*  Use specific types when an "int" might suffice to keep this sane. */
    1.29 +typedef Sint32 (SDLCALL *SDL_DYNAPI_ENTRYFN)(Uint32 apiver, void *table, Uint32 tablesize);
    1.30 +extern DECLSPEC Sint32 SDLCALL SDL_DYNAPI_entry(Uint32, void *, Uint32);
    1.31 +
    1.32 +Sint32
    1.33 +SDL_DYNAPI_entry(Uint32 apiver, void *table, Uint32 tablesize)
    1.34 +{
    1.35 +    return initialize_jumptable(apiver, table, tablesize);
    1.36 +}
    1.37 +
    1.38 +
    1.39  /* Obviously we can't use SDL_LoadObject() to load SDL.  :)  */
    1.40  /* Also obviously, we never close the loaded library. */
    1.41  #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
    1.42 @@ -260,7 +267,7 @@
    1.43  SDL_InitDynamicAPILocked(void)
    1.44  {
    1.45      const char *libname = SDL_getenv_REAL("SDL_DYNAMIC_API");
    1.46 -    SDL_DYNAPI_ENTRYFN entry = SDL_DYNAPI_entry;  /* funcs from here by default. */
    1.47 +    SDL_DYNAPI_ENTRYFN entry = NULL;  /* funcs from here by default. */
    1.48  
    1.49      if (libname) {
    1.50          entry = (SDL_DYNAPI_ENTRYFN) get_sdlapi_entry(libname, "SDL_DYNAPI_entry");
    1.51 @@ -268,16 +275,15 @@
    1.52              /* !!! FIXME: fail to startup here instead? */
    1.53              /* !!! FIXME: definitely warn user. */
    1.54              /* Just fill in the function pointers from this library. */
    1.55 -            entry = SDL_DYNAPI_entry;
    1.56          }
    1.57      }
    1.58  
    1.59 -    if (entry(SDL_DYNAPI_VERSION, &jump_table, sizeof (jump_table)) < 0) {
    1.60 +    if (!entry || (entry(SDL_DYNAPI_VERSION, &jump_table, sizeof (jump_table)) < 0)) {
    1.61          /* !!! FIXME: fail to startup here instead? */
    1.62          /* !!! FIXME: definitely warn user. */
    1.63          /* Just fill in the function pointers from this library. */
    1.64 -        if (entry != SDL_DYNAPI_entry) {
    1.65 -            if (!SDL_DYNAPI_entry(SDL_DYNAPI_VERSION, &jump_table, sizeof (jump_table))) {
    1.66 +        if (!entry) {
    1.67 +            if (!initialize_jumptable(SDL_DYNAPI_VERSION, &jump_table, sizeof (jump_table))) {
    1.68                  /* !!! FIXME: now we're screwed. Should definitely abort now. */
    1.69              }
    1.70          }