Make sure we always copy the data returned using SDL_GetStringRule

This prevents race conditions where calling an API from one thread returns the data and it's freed by updates on another thread
This commit is contained in:
Sam Lantinga 2024-07-18 15:56:41 -07:00
parent ef884c8aa6
commit bb96320cc4
19 changed files with 66 additions and 71 deletions

View file

@ -296,6 +296,8 @@ extern int SDLCALL SDL_WaitSemaphoreTimeoutNS(SDL_Semaphore *sem, Sint64 timeout
extern int SDLCALL SDL_WaitConditionTimeoutNS(SDL_Condition *cond, SDL_Mutex *mutex, Sint64 timeoutNS);
extern SDL_bool SDLCALL SDL_WaitEventTimeoutNS(SDL_Event *event, Sint64 timeoutNS);
extern const char *SDL_CreateTemporaryString(const char *string);
/* Queue `memory` to be passed to SDL_free once the event queue is emptied.
this manages the list of pointers to SDL_AllocateEventMemory, but you
can use it to queue pointers from other subsystems that can die at any

View file

@ -65,7 +65,7 @@ static void SDL_FreePropertyWithCleanup(const void *key, const void *value, void
}
break;
case SDL_PROPERTY_TYPE_STRING:
SDL_FreeLater(property->value.string_value); // this pointer might be given to the app by SDL_GetStringProperty.
SDL_FreeLater(property->value.string_value); // SDL_GetStringProperty() returns this pointer
break;
default:
break;

View file

@ -170,7 +170,7 @@ static int GetDefaultSampleFramesFromFreq(const int freq)
int *SDL_ChannelMapDup(const int *origchmap, int channels)
{
const size_t chmaplen = sizeof (*origchmap) * channels;
int *chmap = (int *) SDL_malloc(chmaplen);
int *chmap = (int *)SDL_malloc(chmaplen);
if (chmap) {
SDL_memcpy(chmap, origchmap, chmaplen);
}
@ -544,8 +544,8 @@ static void DestroyPhysicalAudioDevice(SDL_AudioDevice *device)
SDL_DestroyMutex(device->lock);
SDL_DestroyCondition(device->close_cond);
SDL_free(device->work_buffer);
SDL_FreeLater(device->chmap); // this pointer is handed to the app during SDL_GetAudioDeviceChannelMap
SDL_FreeLater(device->name); // this pointer is handed to the app during SDL_GetAudioDeviceName
SDL_free(device->chmap);
SDL_free(device->name);
SDL_free(device);
}
@ -1432,7 +1432,7 @@ const char *SDL_GetAudioDeviceName(SDL_AudioDeviceID devid)
const char *retval = NULL;
SDL_AudioDevice *device = ObtainPhysicalAudioDevice(devid);
if (device) {
retval = device->name;
retval = SDL_CreateTemporaryString(device->name);
}
ReleaseAudioDevice(device);
@ -1465,8 +1465,8 @@ const int *SDL_GetAudioDeviceChannelMap(SDL_AudioDeviceID devid, int *count)
int channels = 0;
SDL_AudioDevice *device = ObtainPhysicalAudioDeviceDefaultAllowed(devid);
if (device) {
retval = device->chmap;
channels = device->spec.channels;
retval = SDL_FreeLater(SDL_ChannelMapDup(device->chmap, channels));
}
ReleaseAudioDevice(device);

View file

@ -565,7 +565,7 @@ int SDL_SetAudioStreamFormat(SDL_AudioStream *stream, const SDL_AudioSpec *src_s
if (src_spec) {
if (src_spec->channels != stream->src_spec.channels) {
SDL_FreeLater(stream->src_chmap); // this pointer is handed to the app during SDL_GetAudioStreamInputChannelMap
SDL_free(stream->src_chmap);
stream->src_chmap = NULL;
}
SDL_copyp(&stream->src_spec, src_spec);
@ -573,7 +573,7 @@ int SDL_SetAudioStreamFormat(SDL_AudioStream *stream, const SDL_AudioSpec *src_s
if (dst_spec) {
if (dst_spec->channels != stream->dst_spec.channels) {
SDL_FreeLater(stream->dst_chmap); // this pointer is handed to the app during SDL_GetAudioStreamInputChannelMap
SDL_free(stream->dst_chmap);
stream->dst_chmap = NULL;
}
SDL_copyp(&stream->dst_spec, dst_spec);
@ -613,11 +613,11 @@ static int SetAudioStreamChannelMap(SDL_AudioStream *stream, const SDL_AudioSpec
if (!dupmap) {
retval = SDL_SetError("Invalid channel mapping");
} else {
SDL_FreeLater(*stream_chmap); // this pointer is handed to the app during SDL_GetAudioStreamInputChannelMap
SDL_free(*stream_chmap);
*stream_chmap = dupmap;
}
} else {
SDL_FreeLater(*stream_chmap); // this pointer is handed to the app during SDL_GetAudioStreamInputChannelMap
SDL_free(*stream_chmap);
*stream_chmap = NULL;
}
}
@ -642,8 +642,8 @@ const int *SDL_GetAudioStreamInputChannelMap(SDL_AudioStream *stream, int *count
int channels = 0;
if (stream) {
SDL_LockMutex(stream->lock);
retval = stream->src_chmap;
channels = stream->src_spec.channels;
retval = SDL_FreeLater(SDL_ChannelMapDup(stream->src_chmap, channels));
SDL_UnlockMutex(stream->lock);
}
@ -660,8 +660,8 @@ const int *SDL_GetAudioStreamOutputChannelMap(SDL_AudioStream *stream, int *coun
int channels = 0;
if (stream) {
SDL_LockMutex(stream->lock);
retval = stream->dst_chmap;
channels = stream->dst_spec.channels;
retval = SDL_FreeLater(SDL_ChannelMapDup(stream->dst_chmap, channels));
SDL_UnlockMutex(stream->lock);
}

View file

@ -286,7 +286,7 @@ static void DestroyPhysicalCamera(SDL_Camera *device)
camera_driver.impl.FreeDeviceHandle(device);
SDL_DestroyMutex(device->lock);
SDL_free(device->all_specs);
SDL_FreeLater(device->name); // this is returned in SDL_GetCameraName.
SDL_free(device->name);
SDL_free(device);
}
}
@ -674,10 +674,10 @@ int SDL_GetCameraFormat(SDL_Camera *camera, SDL_CameraSpec *spec)
const char *SDL_GetCameraName(SDL_CameraID instance_id)
{
char *retval = NULL;
const char *retval = NULL;
SDL_Camera *device = ObtainPhysicalCamera(instance_id);
if (device) {
retval = device->name;
retval = SDL_CreateTemporaryString(device->name);
ReleaseCamera(device);
}
return retval;

View file

@ -59,13 +59,13 @@ static int SDL_SendDrop(SDL_Window *window, const SDL_EventType evtype, const ch
event.type = evtype;
event.common.timestamp = 0;
if (source) {
event.drop.source = SDL_AllocateEventString(source);
event.drop.source = SDL_CreateTemporaryString(source);
if (!event.drop.source) {
return 0;
}
}
if (data) {
event.drop.data = SDL_AllocateEventString(data);
event.drop.data = SDL_CreateTemporaryString(data);
if (!event.drop.data) {
return 0;
}

View file

@ -290,7 +290,7 @@ void *SDL_AllocateEventMemory(size_t size)
return SDL_FreeLater(SDL_malloc(size));
}
const char *SDL_AllocateEventString(const char *string)
const char *SDL_CreateTemporaryString(const char *string)
{
if (string) {
return SDL_FreeLater(SDL_strdup(string));

View file

@ -40,8 +40,6 @@ extern int SDL_StartEventLoop(void);
extern void SDL_StopEventLoop(void);
extern void SDL_QuitInterrupt(void);
extern const char *SDL_AllocateEventString(const char *string);
extern int SDL_SendAppEvent(SDL_EventType eventType);
extern int SDL_SendKeymapChangedEvent(void);
extern int SDL_SendLocaleChangedEvent(void);

View file

@ -156,7 +156,7 @@ void SDL_RemoveKeyboard(SDL_KeyboardID keyboardID, SDL_bool send_event)
return;
}
SDL_FreeLater(SDL_keyboards[keyboard_index].name);
SDL_free(SDL_keyboards[keyboard_index].name);
if (keyboard_index != SDL_keyboard_count - 1) {
SDL_memcpy(&SDL_keyboards[keyboard_index], &SDL_keyboards[keyboard_index + 1], (SDL_keyboard_count - keyboard_index - 1) * sizeof(SDL_keyboards[keyboard_index]));
@ -207,7 +207,7 @@ const char *SDL_GetKeyboardNameForID(SDL_KeyboardID instance_id)
if (keyboard_index < 0) {
return NULL;
}
return SDL_keyboards[keyboard_index].name;
return SDL_CreateTemporaryString(SDL_keyboards[keyboard_index].name);
}
void SDL_ResetKeyboard(void)
@ -719,7 +719,7 @@ int SDL_SendKeyboardText(const char *text)
event.type = SDL_EVENT_TEXT_INPUT;
event.common.timestamp = 0;
event.text.windowID = keyboard->focus ? keyboard->focus->id : 0;
event.text.text = SDL_AllocateEventString(text);
event.text.text = SDL_CreateTemporaryString(text);
if (!event.text.text) {
return 0;
}
@ -751,7 +751,7 @@ int SDL_SendEditingText(const char *text, int start, int length)
event.edit.windowID = keyboard->focus ? keyboard->focus->id : 0;
event.edit.start = start;
event.edit.length = length;
event.edit.text = SDL_AllocateEventString(text);
event.edit.text = SDL_CreateTemporaryString(text);
if (!event.edit.text) {
return 0;
}
@ -783,7 +783,7 @@ int SDL_SendEditingTextCandidates(char **candidates, int num_candidates, int sel
return 0;
}
for (int i = 0; i < num_candidates; ++i) {
event_candidates[i] = SDL_AllocateEventString(candidates[i]);
event_candidates[i] = SDL_CreateTemporaryString(candidates[i]);
}
event_candidates[num_candidates] = NULL;
event.edit_candidates.candidates = event_candidates;

View file

@ -1017,7 +1017,7 @@ const char *SDL_GetKeyName(SDL_Keycode key)
end = SDL_UCS4ToUTF8(key, name);
*end = '\0';
return SDL_FreeLater(SDL_strdup(name));
return SDL_CreateTemporaryString(name);
}
}

View file

@ -312,7 +312,7 @@ void SDL_RemoveMouse(SDL_MouseID mouseID, SDL_bool send_event)
return;
}
SDL_FreeLater(SDL_mice[mouse_index].name); // SDL_GetMouseNameForID returns this pointer.
SDL_free(SDL_mice[mouse_index].name);
if (mouse_index != SDL_mouse_count - 1) {
SDL_memcpy(&SDL_mice[mouse_index], &SDL_mice[mouse_index + 1], (SDL_mouse_count - mouse_index - 1) * sizeof(SDL_mice[mouse_index]));
@ -376,7 +376,7 @@ const char *SDL_GetMouseNameForID(SDL_MouseID instance_id)
if (mouse_index < 0) {
return NULL;
}
return SDL_mice[mouse_index].name;
return SDL_CreateTemporaryString(SDL_mice[mouse_index].name);
}
void SDL_SetDefaultCursor(SDL_Cursor *cursor)

View file

@ -102,7 +102,10 @@ SDL_Touch *SDL_GetTouch(SDL_TouchID id)
const char *SDL_GetTouchDeviceName(SDL_TouchID id)
{
SDL_Touch *touch = SDL_GetTouch(id);
return touch ? touch->name : NULL;
if (!touch) {
return NULL;
}
return SDL_CreateTemporaryString(touch->name);
}
SDL_TouchDeviceType SDL_GetTouchDeviceType(SDL_TouchID id)
@ -245,7 +248,7 @@ static int SDL_DelFinger(SDL_Touch *touch, SDL_FingerID fingerid)
// Move the deleted finger to just past the end of the active fingers array and shift the active fingers by one.
// This ensures that the descriptor for the now-deleted finger is located at `touch->fingers[touch->num_fingers]`
// and is ready for use in SDL_AddFinger.
SDL_Finger *deleted_finger = touch->fingers[index];
SDL_Finger *deleted_finger = touch->fingers[index];
SDL_memmove(&touch->fingers[index], &touch->fingers[index + 1], (touch->num_fingers - index) * sizeof(touch->fingers[index]));
touch->fingers[touch->num_fingers] = deleted_finger;
}
@ -493,7 +496,7 @@ void SDL_DelTouch(SDL_TouchID id)
SDL_free(touch->fingers[i]);
}
SDL_free(touch->fingers);
SDL_FreeLater(touch->name); // this pointer might be given to the app by SDL_GetTouchDeviceName.
SDL_free(touch->name);
SDL_free(touch);
SDL_num_touch--;

View file

@ -383,8 +383,7 @@ const char * const *SDL_InternalGlobDirectory(const char *path, const char *patt
SDL_free(folded);
SDL_free(pathcpy);
SDL_FreeLater(retval);
return (const char * const *) retval;
return SDL_FreeLater(retval);
}
static int GlobDirectoryGetPathInfo(const char *path, SDL_PathInfo *info, void *userdata)
@ -435,10 +434,7 @@ const char *SDL_GetUserFolder(SDL_Folder folder)
const char *SDL_GetPrefPath(const char *org, const char *app)
{
char *path = SDL_SYS_GetPrefPath(org, app);
if (path) {
SDL_FreeLater(path);
}
return path;
return SDL_FreeLater(path);
}

View file

@ -100,7 +100,7 @@ const char *SDL_GetHapticNameForID(SDL_HapticID instance_id)
if (SDL_GetHapticIndex(instance_id, &device_index)) {
name = SDL_SYS_HapticName(device_index);
}
return name ? SDL_FreeLater(SDL_strdup(name)) : NULL;
return SDL_CreateTemporaryString(name);
}
SDL_Haptic *SDL_OpenHaptic(SDL_HapticID instance_id)
@ -187,9 +187,9 @@ SDL_HapticID SDL_GetHapticID(SDL_Haptic *haptic)
const char *SDL_GetHapticName(SDL_Haptic *haptic)
{
CHECK_HAPTIC_MAGIC(haptic, 0);
CHECK_HAPTIC_MAGIC(haptic, NULL);
return haptic->name;
return SDL_CreateTemporaryString(haptic->name);
}
SDL_bool SDL_IsMouseHaptic(void)
@ -336,7 +336,7 @@ void SDL_CloseHaptic(SDL_Haptic *haptic)
}
/* Free the data associated with this device */
SDL_FreeLater(haptic->name); // this pointer is handed to the app in SDL_GetHapticName()
SDL_free(haptic->name);
SDL_free(haptic);
}

View file

@ -1600,7 +1600,7 @@ static GamepadMapping_t *SDL_PrivateAddMappingForGUID(SDL_JoystickGUID jGUID, co
/* Only overwrite the mapping if the priority is the same or higher. */
if (pGamepadMapping->priority <= priority) {
/* Update existing mapping */
SDL_FreeLater(pGamepadMapping->name); // this is returned in SDL_GetGamepadName.
SDL_free(pGamepadMapping->name);
pGamepadMapping->name = pchName;
SDL_free(pGamepadMapping->mapping);
pGamepadMapping->mapping = pchMapping;
@ -2198,8 +2198,7 @@ const char * const *SDL_GetGamepadMappings(int *count)
SDL_free(mappings);
}
SDL_FreeLater(retval);
return (const char * const *) retval;
return SDL_FreeLater(retval);
}
/*
@ -2221,8 +2220,7 @@ const char *SDL_GetGamepadMappingForGUID(SDL_JoystickGUID guid)
}
SDL_UnlockJoysticks();
SDL_FreeLater(retval);
return retval;
return SDL_FreeLater(retval);
}
/*
@ -2240,8 +2238,7 @@ const char *SDL_GetGamepadMapping(SDL_Gamepad *gamepad)
}
SDL_UnlockJoysticks();
SDL_FreeLater(retval);
return retval;
return SDL_FreeLater(retval);
}
/*
@ -2434,7 +2431,7 @@ const char *SDL_GetGamepadNameForID(SDL_JoystickID instance_id)
if (SDL_strcmp(mapping->name, "*") == 0) {
retval = SDL_GetJoystickNameForID(instance_id);
} else {
retval = mapping->name;
retval = SDL_CreateTemporaryString(mapping->name);
}
}
}
@ -2538,8 +2535,7 @@ const char *SDL_GetGamepadMappingForID(SDL_JoystickID instance_id)
}
SDL_UnlockJoysticks();
SDL_FreeLater(retval);
return retval;
return SDL_FreeLater(retval);
}
/*
@ -3314,7 +3310,7 @@ const char *SDL_GetGamepadName(SDL_Gamepad *gamepad)
gamepad->joystick->steam_handle != 0) {
retval = SDL_GetJoystickName(gamepad->joystick);
} else {
retval = gamepad->name;
retval = SDL_CreateTemporaryString(gamepad->name);
}
}
SDL_UnlockJoysticks();
@ -3707,7 +3703,7 @@ void SDL_QuitGamepadMappings(void)
while (s_pSupportedGamepads) {
pGamepadMap = s_pSupportedGamepads;
s_pSupportedGamepads = s_pSupportedGamepads->next;
SDL_FreeLater(pGamepadMap->name); // this is returned in SDL_GetGamepadName.
SDL_free(pGamepadMap->name);
SDL_free(pGamepadMap->mapping);
SDL_free(pGamepadMap);
}

View file

@ -780,13 +780,13 @@ const char *SDL_GetJoystickNameForID(SDL_JoystickID instance_id)
SDL_LockJoysticks();
info = SDL_GetJoystickVirtualGamepadInfoForID(instance_id);
if (info) {
name = info->name;
name = SDL_CreateTemporaryString(info->name);
} else if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
name = driver->GetDeviceName(device_index);
name = SDL_CreateTemporaryString(driver->GetDeviceName(device_index));
}
SDL_UnlockJoysticks();
return name ? SDL_FreeLater(SDL_strdup(name)) : NULL;
return name;
}
/*
@ -800,14 +800,14 @@ const char *SDL_GetJoystickPathForID(SDL_JoystickID instance_id)
SDL_LockJoysticks();
if (SDL_GetDriverAndJoystickIndex(instance_id, &driver, &device_index)) {
path = driver->GetDevicePath(device_index);
path = SDL_CreateTemporaryString(driver->GetDevicePath(device_index));
}
SDL_UnlockJoysticks();
if (!path) {
SDL_Unsupported();
}
return path ? SDL_FreeLater(SDL_strdup(path)) : NULL;
return path;
}
/*
@ -1653,9 +1653,9 @@ const char *SDL_GetJoystickName(SDL_Joystick *joystick)
info = SDL_GetJoystickVirtualGamepadInfoForID(joystick->instance_id);
if (info) {
retval = info->name;
retval = SDL_CreateTemporaryString(info->name);
} else {
retval = joystick->name;
retval = SDL_CreateTemporaryString(joystick->name);
}
}
SDL_UnlockJoysticks();
@ -1675,7 +1675,7 @@ const char *SDL_GetJoystickPath(SDL_Joystick *joystick)
CHECK_JOYSTICK_MAGIC(joystick, NULL);
if (joystick->path) {
retval = joystick->path;
retval = SDL_CreateTemporaryString(joystick->path);
} else {
SDL_Unsupported();
retval = NULL;
@ -1884,9 +1884,9 @@ void SDL_CloseJoystick(SDL_Joystick *joystick)
}
/* Free the data associated with this joystick */
SDL_FreeLater(joystick->name); // SDL_GetJoystickName returns this pointer.
SDL_FreeLater(joystick->path); // SDL_GetJoystickPath returns this pointer.
SDL_FreeLater(joystick->serial); // SDL_GetJoystickSerial returns this pointer.
SDL_free(joystick->name);
SDL_free(joystick->path);
SDL_free(joystick->serial);
SDL_free(joystick->axes);
SDL_free(joystick->balls);
SDL_free(joystick->hats);
@ -3431,7 +3431,7 @@ const char *SDL_GetJoystickSerial(SDL_Joystick *joystick)
{
CHECK_JOYSTICK_MAGIC(joystick, NULL);
retval = joystick->serial;
retval = SDL_CreateTemporaryString(joystick->serial);
}
SDL_UnlockJoysticks();

View file

@ -246,11 +246,11 @@ const char *SDL_GetSensorNameForID(SDL_SensorID instance_id)
SDL_LockSensors();
if (SDL_GetDriverAndSensorIndex(instance_id, &driver, &device_index)) {
name = driver->GetDeviceName(device_index);
name = SDL_CreateTemporaryString(driver->GetDeviceName(device_index));
}
SDL_UnlockSensors();
return name ? SDL_FreeLater(SDL_strdup(name)) : NULL;
return name;
}
SDL_SensorType SDL_GetSensorTypeForID(SDL_SensorID instance_id)
@ -407,7 +407,7 @@ const char *SDL_GetSensorName(SDL_Sensor *sensor)
{
CHECK_SENSOR_MAGIC(sensor, NULL);
retval = sensor->name;
retval = SDL_CreateTemporaryString(sensor->name);
}
SDL_UnlockSensors();
@ -526,7 +526,7 @@ void SDL_CloseSensor(SDL_Sensor *sensor)
}
/* Free the data associated with this sensor */
SDL_FreeLater(sensor->name); // this pointer gets handed to the app by SDL_GetSensorName().
SDL_free(sensor->name);
SDL_free(sensor);
}
SDL_UnlockSensors();

View file

@ -329,7 +329,7 @@ void SDL_RunThread(SDL_Thread *thread)
if (!SDL_AtomicCompareAndSwap(&thread->state, SDL_THREAD_STATE_ALIVE, SDL_THREAD_STATE_ZOMBIE)) {
/* Clean up if something already detached us. */
if (SDL_AtomicCompareAndSwap(&thread->state, SDL_THREAD_STATE_DETACHED, SDL_THREAD_STATE_CLEANED)) {
SDL_FreeLater(thread->name);
SDL_free(thread->name); /* Can't free later, we've already cleaned up TLS */
SDL_free(thread);
}
}

View file

@ -349,7 +349,7 @@ int SDL_SetPrimarySelectionText(const char *text)
return -1;
}
} else {
SDL_FreeLater(_this->primary_selection_text); // this pointer might be given to the app by SDL_GetPrimarySelectionText.
SDL_FreeLater(_this->primary_selection_text); // SDL_GetPrimarySelectionText() returns this pointer.
_this->primary_selection_text = SDL_strdup(text);
}