Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions include/SDL3/SDL_hints.h
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,20 @@ extern "C" {
*/
#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
* asyncify.
Expand Down
4 changes: 2 additions & 2 deletions src/SDL.c
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ static bool SDL_ValidMetadataProperty(const char *name)

bool SDL_SetAppMetadataProperty(const char *name, const char *value)
{
if (!SDL_ValidMetadataProperty(name)) {
CHECK_PARAM(!SDL_ValidMetadataProperty(name)) {
return SDL_InvalidParamError("name");
}

Expand All @@ -157,7 +157,7 @@ bool SDL_SetAppMetadataProperty(const char *name, const char *value)

const char *SDL_GetAppMetadataProperty(const char *name)
{
if (!SDL_ValidMetadataProperty(name)) {
CHECK_PARAM(!SDL_ValidMetadataProperty(name)) {
SDL_InvalidParamError("name");
return NULL;
}
Expand Down
13 changes: 7 additions & 6 deletions src/SDL_hashtable.c
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,7 @@ static bool maybe_resize(SDL_HashTable *ht)

bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *value, bool replace)
{
if (!table) {
CHECK_PARAM(!table) {
return SDL_InvalidParamError("table");
}

Expand Down Expand Up @@ -338,7 +338,7 @@ bool SDL_InsertIntoHashTable(SDL_HashTable *table, const void *key, const void *

bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void **value)
{
if (!table) {
CHECK_PARAM(!table) {
if (value) {
*value = NULL;
}
Expand All @@ -364,7 +364,7 @@ bool SDL_FindInHashTable(const SDL_HashTable *table, const void *key, const void

bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key)
{
if (!table) {
CHECK_PARAM(!table) {
return SDL_InvalidParamError("table");
}

Expand All @@ -384,9 +384,10 @@ bool SDL_RemoveFromHashTable(SDL_HashTable *table, const void *key)

bool SDL_IterateHashTable(const SDL_HashTable *table, SDL_HashTableIterateCallback callback, void *userdata)
{
if (!table) {
CHECK_PARAM(!table) {
return SDL_InvalidParamError("table");
} else if (!callback) {
}
CHECK_PARAM(!callback) {
return SDL_InvalidParamError("callback");
}

Expand All @@ -410,7 +411,7 @@ bool SDL_IterateHashTable(const SDL_HashTable *table, SDL_HashTableIterateCallba

bool SDL_HashTableEmpty(SDL_HashTable *table)
{
if (!table) {
CHECK_PARAM(!table) {
return SDL_InvalidParamError("table");
}

Expand Down
9 changes: 5 additions & 4 deletions src/SDL_hints.c
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ static const char *GetHintEnvironmentVariable(const char *name)

bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriority priority)
{
if (!name || !*name) {
CHECK_PARAM(!name || !*name) {
return SDL_InvalidParamError("name");
}

Expand Down Expand Up @@ -165,7 +165,7 @@ bool SDL_SetHintWithPriority(const char *name, const char *value, SDL_HintPriori

bool SDL_ResetHint(const char *name)
{
if (!name || !*name) {
CHECK_PARAM(!name || !*name) {
return SDL_InvalidParamError("name");
}

Expand Down Expand Up @@ -316,9 +316,10 @@ bool SDL_GetHintBoolean(const char *name, bool default_value)

bool SDL_AddHintCallback(const char *name, SDL_HintCallback callback, void *userdata)
{
if (!name || !*name) {
CHECK_PARAM(!name || !*name) {
return SDL_InvalidParamError("name");
} else if (!callback) {
}
CHECK_PARAM(!callback) {
return SDL_InvalidParamError("callback");
}

Expand Down
15 changes: 15 additions & 0 deletions src/SDL_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,21 @@ extern SDL_NORETURN void SDL_ExitProcess(int exitcode);
#define POP_SDL_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
extern void SDL_InitMainThread(void);

Expand Down
2 changes: 1 addition & 1 deletion src/SDL_log.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ bool SDL_SetLogPriorityPrefix(SDL_LogPriority priority, const char *prefix)
{
char *prefix_copy;

if (priority <= SDL_LOG_PRIORITY_INVALID || priority >= SDL_LOG_PRIORITY_COUNT) {
CHECK_PARAM(priority <= SDL_LOG_PRIORITY_INVALID || priority >= SDL_LOG_PRIORITY_COUNT) {
return SDL_InvalidParamError("priority");
}

Expand Down
24 changes: 12 additions & 12 deletions src/SDL_properties.c
Original file line number Diff line number Diff line change
Expand Up @@ -250,22 +250,22 @@ static bool SDLCALL CopyOneProperty(void *userdata, const SDL_HashTable *table,

bool SDL_CopyProperties(SDL_PropertiesID src, SDL_PropertiesID dst)
{
if (!src) {
CHECK_PARAM(!src) {
return SDL_InvalidParamError("src");
}
if (!dst) {
CHECK_PARAM(!dst) {
return SDL_InvalidParamError("dst");
}

SDL_Properties *src_properties = NULL;
SDL_Properties *dst_properties = NULL;

SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)src, (const void **)&src_properties);
if (!src_properties) {
CHECK_PARAM(!src_properties) {
return SDL_InvalidParamError("src");
}
SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)dst, (const void **)&dst_properties);
if (!dst_properties) {
CHECK_PARAM(!dst_properties) {
return SDL_InvalidParamError("dst");
}

Expand All @@ -287,12 +287,12 @@ bool SDL_LockProperties(SDL_PropertiesID props)
{
SDL_Properties *properties = NULL;

if (!props) {
CHECK_PARAM(!props) {
return SDL_InvalidParamError("props");
}

SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
if (!properties) {
CHECK_PARAM(!properties) {
return SDL_InvalidParamError("props");
}

Expand Down Expand Up @@ -321,17 +321,17 @@ static bool SDL_PrivateSetProperty(SDL_PropertiesID props, const char *name, SDL
SDL_Properties *properties = NULL;
bool result = true;

if (!props) {
CHECK_PARAM(!props) {
SDL_FreePropertyWithCleanup(NULL, property, NULL, true);
return SDL_InvalidParamError("props");
}
if (!name || !*name) {
CHECK_PARAM(!name || !*name) {
SDL_FreePropertyWithCleanup(NULL, property, NULL, true);
return SDL_InvalidParamError("name");
}

SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
if (!properties) {
CHECK_PARAM(!properties) {
SDL_FreePropertyWithCleanup(NULL, property, NULL, true);
return SDL_InvalidParamError("props");
}
Expand Down Expand Up @@ -755,15 +755,15 @@ bool SDL_EnumerateProperties(SDL_PropertiesID props, SDL_EnumeratePropertiesCall
{
SDL_Properties *properties = NULL;

if (!props) {
CHECK_PARAM(!props) {
return SDL_InvalidParamError("props");
}
if (!callback) {
CHECK_PARAM(!callback) {
return SDL_InvalidParamError("callback");
}

SDL_FindInHashTable(SDL_properties, (const void *)(uintptr_t)props, (const void **)&properties);
if (!properties) {
CHECK_PARAM(!properties) {
return SDL_InvalidParamError("props");
}

Expand Down
34 changes: 29 additions & 5 deletions src/SDL_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,32 @@ Uint32 SDL_GetNextObjectID(void)

static SDL_InitState SDL_objects_init;
static SDL_HashTable *SDL_objects;
bool SDL_object_validation = false;

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)
{
Expand All @@ -159,6 +185,7 @@ void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid)
if (!initialized) {
return;
}
SDL_AddHintCallback(SDL_HINT_INVALID_PARAM_CHECKS, SDL_InvalidParamChecksChanged, NULL);
}

if (valid) {
Expand All @@ -168,12 +195,8 @@ void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid)
}
}

bool SDL_ObjectValid(void *object, SDL_ObjectType type)
bool SDL_FindObject(void *object, SDL_ObjectType type)
{
if (!object) {
return false;
}

const void *object_type;
if (!SDL_FindInHashTable(SDL_objects, object, &object_type)) {
return false;
Expand Down Expand Up @@ -242,6 +265,7 @@ void SDL_SetObjectsInvalid(void)
SDL_DestroyHashTable(SDL_objects);
SDL_objects = NULL;
SDL_SetInitialized(&SDL_objects_init, false);
SDL_RemoveHintCallback(SDL_HINT_INVALID_PARAM_CHECKS, SDL_InvalidParamChecksChanged, NULL);
}
}

Expand Down
17 changes: 16 additions & 1 deletion src/SDL_utils_c.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,10 +67,25 @@ typedef enum

extern Uint32 SDL_GetNextObjectID(void);
extern void SDL_SetObjectValid(void *object, SDL_ObjectType type, bool valid);
extern bool SDL_ObjectValid(void *object, SDL_ObjectType type);
extern bool SDL_FindObject(void *object, SDL_ObjectType type);
extern int SDL_GetObjects(SDL_ObjectType type, void **objects, int count);
extern void SDL_SetObjectsInvalid(void);

extern bool SDL_object_validation;

SDL_FORCE_INLINE bool SDL_ObjectValid(void *object, SDL_ObjectType type)
{
if (!object) {
return false;
}

if (!SDL_object_validation) {
return true;
}

return SDL_FindObject(object, type);
}

extern const char *SDL_GetPersistentString(const char *string);

extern char *SDL_CreateDeviceName(Uint16 vendor, Uint16 product, const char *vendor_name, const char *product_name, const char *default_name);
Expand Down
24 changes: 14 additions & 10 deletions src/audio/SDL_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,11 @@ int SDL_GetNumAudioDrivers(void)

const char *SDL_GetAudioDriver(int index)
{
if (index >= 0 && index < SDL_GetNumAudioDrivers()) {
return deduped_bootstrap[index]->name;
CHECK_PARAM(index < 0 || index >= SDL_GetNumAudioDrivers()) {
SDL_InvalidParamError("index");
return NULL;
}
SDL_InvalidParamError("index");
return NULL;
return deduped_bootstrap[index]->name;
}

const char *SDL_GetCurrentAudioDriver(void)
Expand Down Expand Up @@ -1576,7 +1576,7 @@ const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)

bool SDL_GetAudioDeviceFormat(SDL_AudioDeviceID devid, SDL_AudioSpec *spec, int *sample_frames)
{
if (!spec) {
CHECK_PARAM(!spec) {
return SDL_InvalidParamError("spec");
}

Expand Down Expand Up @@ -1937,7 +1937,7 @@ float SDL_GetAudioDeviceGain(SDL_AudioDeviceID devid)

bool SDL_SetAudioDeviceGain(SDL_AudioDeviceID devid, float gain)
{
if (gain < 0.0f) {
CHECK_PARAM(gain < 0.0f) {
return SDL_InvalidParamError("gain");
}

Expand Down Expand Up @@ -1986,11 +1986,15 @@ bool SDL_BindAudioStreams(SDL_AudioDeviceID devid, SDL_AudioStream * const *stre

if (num_streams == 0) {
return true; // nothing to do
} else if (num_streams < 0) {
}

CHECK_PARAM(num_streams < 0) {
return SDL_InvalidParamError("num_streams");
} else if (!streams) {
}
CHECK_PARAM(!streams) {
return SDL_InvalidParamError("streams");
} else if (SDL_IsAudioDevicePhysical(devid)) {
}
CHECK_PARAM(SDL_IsAudioDevicePhysical(devid)) {
return SDL_SetError("Audio streams are bound to device ids from SDL_OpenAudioDevice, not raw physical devices");
}

Expand Down Expand Up @@ -2150,7 +2154,7 @@ SDL_AudioDeviceID SDL_GetAudioStreamDevice(SDL_AudioStream *stream)
{
SDL_AudioDeviceID result = 0;

if (!stream) {
CHECK_PARAM(!stream) {
SDL_InvalidParamError("stream");
return 0;
}
Expand Down
Loading
Loading