Prevent crashes if freed objects are passed to SDL API functions

Instead of using the magic tag in the object, we'll actually keep track of valid objects

Fixes https://github.com/libsdl-org/SDL/issues/9869
Fixes https://github.com/libsdl-org/SDL/issues/9235
This commit is contained in:
Sam Lantinga
2024-06-03 04:09:28 -07:00
parent 57a15933cd
commit b0e93e4e63
28 changed files with 191 additions and 126 deletions

View File

@@ -22,7 +22,6 @@
/* This is the gamepad API for Simple DirectMedia Layer */
#include "../SDL_utils_c.h"
#include "SDL_sysjoystick.h"
#include "SDL_joystick_c.h"
#include "SDL_steam_virtual_gamepad.h"
@@ -104,15 +103,12 @@ static GamepadMapping_t *s_pSupportedGamepads SDL_GUARDED_BY(SDL_joystick_lock)
static GamepadMapping_t *s_pDefaultMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static GamepadMapping_t *s_pXInputMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static MappingChangeTracker *s_mappingChangeTracker SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
static char gamepad_magic;
#define _guarded SDL_GUARDED_BY(SDL_joystick_lock)
/* The SDL gamepad structure */
struct SDL_Gamepad
{
const void *magic _guarded;
SDL_Joystick *joystick _guarded; /* underlying joystick device */
int ref_count _guarded;
@@ -131,12 +127,12 @@ struct SDL_Gamepad
#undef _guarded
#define CHECK_GAMEPAD_MAGIC(gamepad, retval) \
if (!gamepad || gamepad->magic != &gamepad_magic || \
!SDL_IsJoystickValid(gamepad->joystick)) { \
SDL_InvalidParamError("gamepad"); \
SDL_UnlockJoysticks(); \
return retval; \
#define CHECK_GAMEPAD_MAGIC(gamepad, retval) \
if (!SDL_ObjectValid(gamepad, SDL_OBJECT_TYPE_GAMEPAD) || \
!SDL_IsJoystickValid(gamepad->joystick)) { \
SDL_InvalidParamError("gamepad"); \
SDL_UnlockJoysticks(); \
return retval; \
}
static SDL_vidpid_list SDL_allowed_gamepads = {
@@ -2683,7 +2679,7 @@ SDL_Gamepad *SDL_OpenGamepad(SDL_JoystickID instance_id)
SDL_UnlockJoysticks();
return NULL;
}
gamepad->magic = &gamepad_magic;
SDL_SetObjectValid(gamepad, SDL_OBJECT_TYPE_GAMEPAD, SDL_TRUE);
gamepad->joystick = SDL_OpenJoystick(instance_id);
if (!gamepad->joystick) {
@@ -3612,7 +3608,7 @@ void SDL_CloseGamepad(SDL_Gamepad *gamepad)
SDL_LockJoysticks();
if (!gamepad || gamepad->magic != &gamepad_magic) {
if (!SDL_ObjectValid(gamepad, SDL_OBJECT_TYPE_GAMEPAD)) {
SDL_UnlockJoysticks();
return;
}
@@ -3641,7 +3637,7 @@ void SDL_CloseGamepad(SDL_Gamepad *gamepad)
gamepadlist = gamepadlist->next;
}
gamepad->magic = NULL;
SDL_SetObjectValid(gamepad, SDL_OBJECT_TYPE_GAMEPAD, SDL_FALSE);
SDL_free(gamepad->bindings);
SDL_free(gamepad->last_match_axis);
SDL_free(gamepad->last_hat_mask);