Fixed double-free during multi-threaded hidapi access

The error string is not protected by a mutex, and can be set from multiple threads at the same time. Without this change, it can be double-freed. It can still be double-allocated, leading to a memory leak, but at least it won't crash now.

Signed-off-by: Sam Lantinga <slouken@libsdl.org>
main
Sam Lantinga 2023-05-26 20:28:20 -07:00
parent 860e52c99e
commit 2b386b6c80
4 changed files with 45 additions and 8 deletions

View File

@ -529,6 +529,7 @@ static void HIDAPI_ShutdownDiscovery(void)
/* Platform HIDAPI Implementation */
#define HIDAPI_IGNORE_DEVICE(VID, PID) SDL_HIDAPI_ShouldIgnoreDevice(VID, PID)
#define HIDAPI_ATOMIC_SET_POINTER(a, v) SDL_AtomicSetPtr((void **)a, v)
struct PLATFORM_hid_device_;
typedef struct PLATFORM_hid_device_ PLATFORM_hid_device;

View File

@ -130,8 +130,19 @@ static wchar_t *utf8_to_wchar_t(const char *utf8)
* Use register_error_str(NULL) to free the error message completely. */
static void register_error_str(wchar_t **error_str, const char *msg)
{
free(*error_str);
*error_str = utf8_to_wchar_t(msg);
wchar_t *old_string;
#ifdef HIDAPI_ATOMIC_SET_POINTER
old_string = HIDAPI_ATOMIC_SET_POINTER(error_str, NULL);
#else
old_string = *error_str; *error_str = NULL;
#endif
if (old_string) {
free(old_string);
}
if (msg) {
*error_str = utf8_to_wchar_t(msg);
}
}
/* Semilar to register_error_str, but allows passing a format string with va_list args into this function. */

View File

@ -243,8 +243,19 @@ static wchar_t *utf8_to_wchar_t(const char *utf8)
* Use register_error_str(NULL) to free the error message completely. */
static void register_error_str(wchar_t **error_str, const char *msg)
{
free(*error_str);
*error_str = utf8_to_wchar_t(msg);
wchar_t *old_string;
#ifdef HIDAPI_ATOMIC_SET_POINTER
old_string = HIDAPI_ATOMIC_SET_POINTER(error_str, NULL);
#else
old_string = *error_str; *error_str = NULL;
#endif
if (old_string) {
free(old_string);
}
if (msg) {
*error_str = utf8_to_wchar_t(msg);
}
}
/* Similar to register_error_str, but allows passing a format string with va_list args into this function. */

View File

@ -255,8 +255,15 @@ static void free_hid_device(hid_device *dev)
static void register_winapi_error_to_buffer(wchar_t **error_buffer, const WCHAR *op)
{
free(*error_buffer);
*error_buffer = NULL;
wchar_t *old_string;
#ifdef HIDAPI_ATOMIC_SET_POINTER
old_string = HIDAPI_ATOMIC_SET_POINTER(error_buffer, NULL);
#else
old_string = *error_buffer; *error_buffer = NULL;
#endif
if (old_string) {
free(old_string);
}
/* Only clear out error messages if NULL is passed into op */
if (!op) {
@ -320,8 +327,15 @@ static void register_winapi_error_to_buffer(wchar_t **error_buffer, const WCHAR
static void register_string_error_to_buffer(wchar_t **error_buffer, const WCHAR *string_error)
{
free(*error_buffer);
*error_buffer = NULL;
wchar_t *old_string;
#ifdef HIDAPI_ATOMIC_SET_POINTER
old_string = HIDAPI_ATOMIC_SET_POINTER(error_buffer, NULL);
#else
old_string = *error_buffer; *error_buffer = NULL;
#endif
if (old_string) {
free(old_string);
}
if (string_error) {
*error_buffer = _wcsdup(string_error);