mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-09-29 14:38:29 +00:00
Improved handling of function parameter validation
SDL supports the following use cases: * Normal operation with fast parameter checks (default): SDL_SetHint(SDL_HINT_INVALID_PARAM_CHECKS, "1"); * Object parameters are checked for use-after-free issues: SDL_SetHint(SDL_HINT_INVALID_PARAM_CHECKS, "2"); * Enable full validation, plus assert on invalid parameters: #define SDL_ASSERT_INVALID_PARAMS * Disable all parameter validation: #define SDL_DISABLE_INVALID_PARAMS
This commit is contained in:
@@ -685,6 +685,20 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS"
|
#define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the level of checking for invalid parameters passed to SDL functions.
|
||||||
|
*
|
||||||
|
* The variable can be set to the following values:
|
||||||
|
*
|
||||||
|
* - "1": Enable fast parameter error checking, e.g. quick NULL checks, etc. (default)
|
||||||
|
* - "2": Enable full parameter error checking, e.g. validating objects are the correct type, etc.
|
||||||
|
*
|
||||||
|
* This hint can be set anytime.
|
||||||
|
*
|
||||||
|
* \since This hint is available since SDL 3.4.0.
|
||||||
|
*/
|
||||||
|
#define SDL_HINT_INVALID_PARAM_CHECKS "SDL_INVALID_PARAM_CHECKS"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Disable giving back control to the browser automatically when running with
|
* Disable giving back control to the browser automatically when running with
|
||||||
* asyncify.
|
* asyncify.
|
||||||
|
@@ -290,6 +290,21 @@ extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
|
|||||||
#define POP_SDL_ERROR() \
|
#define POP_SDL_ERROR() \
|
||||||
SDL_SetError("%s", _error); SDL_free(_error); }
|
SDL_SetError("%s", _error); SDL_free(_error); }
|
||||||
|
|
||||||
|
#if defined(SDL_DISABLE_INVALID_PARAMS)
|
||||||
|
#ifdef DEBUG
|
||||||
|
// If you define SDL_DISABLE_INVALID_PARAMS, you're promising that you'll
|
||||||
|
// never pass an invalid parameter to SDL, since it may crash or lead to
|
||||||
|
// hard to diagnose bugs. Let's assert that this is true in debug builds.
|
||||||
|
#define CHECK_PARAM(invalid) SDL_assert_always(!(invalid)); if (false)
|
||||||
|
#else
|
||||||
|
#define CHECK_PARAM(invalid) if (false)
|
||||||
|
#endif
|
||||||
|
#elif defined(SDL_ASSERT_INVALID_PARAMS)
|
||||||
|
#define CHECK_PARAM(invalid) SDL_assert_always(!(invalid)); if (invalid)
|
||||||
|
#else
|
||||||
|
#define CHECK_PARAM(invalid) if (invalid)
|
||||||
|
#endif
|
||||||
|
|
||||||
// Do any initialization that needs to happen before threads are started
|
// Do any initialization that needs to happen before threads are started
|
||||||
extern void SDL_InitMainThread(void);
|
extern void SDL_InitMainThread(void);
|
||||||
|
|
||||||
|
@@ -137,6 +137,32 @@ Uint32 SDL_GetNextObjectID(void)
|
|||||||
|
|
||||||
static SDL_InitState SDL_objects_init;
|
static SDL_InitState SDL_objects_init;
|
||||||
static SDL_HashTable *SDL_objects;
|
static SDL_HashTable *SDL_objects;
|
||||||
|
static bool SDL_object_validation;
|
||||||
|
|
||||||
|
static void SDLCALL SDL_InvalidParamChecksChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
|
||||||
|
{
|
||||||
|
bool validation_enabled = false;
|
||||||
|
|
||||||
|
#ifdef SDL_ASSERT_INVALID_PARAMS
|
||||||
|
// Full validation is enabled by default
|
||||||
|
validation_enabled = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (hint) {
|
||||||
|
switch (*hint) {
|
||||||
|
case '0':
|
||||||
|
case '1':
|
||||||
|
validation_enabled = false;
|
||||||
|
break;
|
||||||
|
case '2':
|
||||||
|
validation_enabled = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SDL_object_validation = validation_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
static Uint32 SDLCALL SDL_HashObject(void *unused, const void *key)
|
static Uint32 SDLCALL SDL_HashObject(void *unused, const void *key)
|
||||||
{
|
{
|
||||||
@@ -159,6 +185,7 @@ void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid)
|
|||||||
if (!initialized) {
|
if (!initialized) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
SDL_AddHintCallback(SDL_HINT_INVALID_PARAM_CHECKS, SDL_InvalidParamChecksChanged, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid) {
|
if (valid) {
|
||||||
@@ -174,6 +201,10 @@ bool SDL_ObjectValid(void *object, SDL_ObjectType type)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!SDL_object_validation) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const void *object_type;
|
const void *object_type;
|
||||||
if (!SDL_FindInHashTable(SDL_objects, object, &object_type)) {
|
if (!SDL_FindInHashTable(SDL_objects, object, &object_type)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -242,6 +273,7 @@ void SDL_SetObjectsInvalid(void)
|
|||||||
SDL_DestroyHashTable(SDL_objects);
|
SDL_DestroyHashTable(SDL_objects);
|
||||||
SDL_objects = NULL;
|
SDL_objects = NULL;
|
||||||
SDL_SetInitialized(&SDL_objects_init, false);
|
SDL_SetInitialized(&SDL_objects_init, false);
|
||||||
|
SDL_RemoveHintCallback(SDL_HINT_INVALID_PARAM_CHECKS, SDL_InvalidParamChecksChanged, NULL);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user