Skip to content

Commit 43eae60

Browse files
committed
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
1 parent aca9bd0 commit 43eae60

File tree

4 files changed

+577
-345
lines changed

4 files changed

+577
-345
lines changed

include/SDL3/SDL_hints.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -685,6 +685,20 @@ extern "C" {
685685
*/
686686
#define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS"
687687

688+
/**
689+
* Set the level of checking for invalid parameters passed to SDL functions.
690+
*
691+
* The variable can be set to the following values:
692+
*
693+
* - "1": Enable fast parameter error checking, e.g. quick NULL checks, etc. (default)
694+
* - "2": Enable full parameter error checking, e.g. validating objects are the correct type, etc.
695+
*
696+
* This hint can be set anytime.
697+
*
698+
* \since This hint is available since SDL 3.4.0.
699+
*/
700+
#define SDL_HINT_INVALID_PARAM_CHECKS "SDL_INVALID_PARAM_CHECKS"
701+
688702
/**
689703
* Disable giving back control to the browser automatically when running with
690704
* asyncify.

src/SDL_internal.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,14 @@ extern "C" {
272272
#define POP_SDL_ERROR() \
273273
SDL_SetError("%s", _error); SDL_free(_error); }
274274

275+
#if defined(SDL_DISABLE_INVALID_PARAMS)
276+
#define CHECK_PARAM(invalid) if (false)
277+
#elif defined(SDL_ASSERT_INVALID_PARAMS)
278+
#define CHECK_PARAM(invalid) SDL_assert_always(!(invalid)); if (invalid)
279+
#else
280+
#define CHECK_PARAM(invalid) if (invalid)
281+
#endif
282+
275283
// Do any initialization that needs to happen before threads are started
276284
extern void SDL_InitMainThread(void);
277285

src/SDL_utils.c

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,32 @@ Uint32 SDL_GetNextObjectID(void)
137137

138138
static SDL_InitState SDL_objects_init;
139139
static SDL_HashTable *SDL_objects;
140+
static bool SDL_object_validation;
141+
142+
static void SDLCALL SDL_InvalidParamChecksChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
143+
{
144+
bool validation_enabled = false;
145+
146+
#ifdef SDL_ASSERT_INVALID_PARAMS
147+
// Full validation is enabled by default
148+
validation_enabled = true;
149+
#endif
150+
151+
if (hint) {
152+
switch (*hint) {
153+
case '0':
154+
case '1':
155+
validation_enabled = false;
156+
break;
157+
case '2':
158+
validation_enabled = true;
159+
break;
160+
default:
161+
break;
162+
}
163+
}
164+
SDL_object_validation = validation_enabled;
165+
}
140166

141167
static Uint32 SDLCALL SDL_HashObject(void *unused, const void *key)
142168
{
@@ -159,6 +185,7 @@ void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid)
159185
if (!initialized) {
160186
return;
161187
}
188+
SDL_AddHintCallback(SDL_HINT_INVALID_PARAM_CHECKS, SDL_InvalidParamChecksChanged, NULL);
162189
}
163190

164191
if (valid) {
@@ -174,6 +201,10 @@ bool SDL_ObjectValid(void *object, SDL_ObjectType type)
174201
return false;
175202
}
176203

204+
if (!SDL_object_validation) {
205+
return true;
206+
}
207+
177208
const void *object_type;
178209
if (!SDL_FindInHashTable(SDL_objects, object, &object_type)) {
179210
return false;
@@ -242,6 +273,7 @@ void SDL_SetObjectsInvalid(void)
242273
SDL_DestroyHashTable(SDL_objects);
243274
SDL_objects = NULL;
244275
SDL_SetInitialized(&SDL_objects_init, false);
276+
SDL_RemoveHintCallback(SDL_HINT_INVALID_PARAM_CHECKS, SDL_InvalidParamChecksChanged, NULL);
245277
}
246278
}
247279

0 commit comments

Comments
 (0)