From d058781f71839d4cb979bb1c41fee1eef0d6c7b4 Mon Sep 17 00:00:00 2001 From: Frank Praznik Date: Mon, 17 Nov 2025 10:22:18 -0500 Subject: [PATCH] mouse: Fix memory leak if events are sent after shutdown Only allocate memory for source events if the mouse system is in the initialized state, otherwise, spurious events during shutdown can cause a leak. --- src/events/SDL_mouse.c | 62 ++++++++++++++++++++++-------------------- 1 file changed, 32 insertions(+), 30 deletions(-) diff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c index bc3e5c47aa..5aee36bd33 100644 --- a/src/events/SDL_mouse.c +++ b/src/events/SDL_mouse.c @@ -39,7 +39,7 @@ static SDL_Mouse SDL_mouse; static int SDL_mouse_count; static SDL_MouseID *SDL_mice; static SDL_HashTable *SDL_mouse_names; -static bool SDL_mouse_quitting; +static bool SDL_mouse_initialized; // for mapping mouse events to touch static bool track_mouse_down = false; @@ -250,6 +250,8 @@ bool SDL_PreInitMouse(void) { SDL_Mouse *mouse = SDL_GetMouse(); + SDL_mouse_initialized = true; + SDL_zerop(mouse); SDL_AddHintCallback(SDL_HINT_MOUSE_DOUBLE_CLICK_TIME, @@ -401,7 +403,7 @@ void SDL_RemoveMouse(SDL_MouseID mouseID) } } - if (!SDL_mouse_quitting) { + if (SDL_mouse_initialized) { SDL_Event event; SDL_zero(event); event.type = SDL_EVENT_MOUSE_REMOVED; @@ -846,38 +848,40 @@ static SDL_MouseInputSource *GetMouseInputSource(SDL_Mouse *mouse, SDL_MouseID m SDL_MouseInputSource *source, *match = NULL, *sources; int i; - for (i = 0; i < mouse->num_sources; ++i) { - source = &mouse->sources[i]; - if (source->mouseID == mouseID) { - match = source; - break; - } - } - - if (!down && (!match || !(match->buttonstate & SDL_BUTTON_MASK(button)))) { - /* This might be a button release from a transition between mouse messages and raw input. - * See if there's another mouse source that already has that button down and use that. - */ + if (SDL_mouse_initialized) { for (i = 0; i < mouse->num_sources; ++i) { source = &mouse->sources[i]; - if ((source->buttonstate & SDL_BUTTON_MASK(button))) { + if (source->mouseID == mouseID) { match = source; break; } } - } - if (match) { - return match; - } - sources = (SDL_MouseInputSource *)SDL_realloc(mouse->sources, (mouse->num_sources + 1) * sizeof(*mouse->sources)); - if (sources) { - mouse->sources = sources; - ++mouse->num_sources; - source = &sources[mouse->num_sources - 1]; - SDL_zerop(source); - source->mouseID = mouseID; - return source; + if (!down && (!match || !(match->buttonstate & SDL_BUTTON_MASK(button)))) { + /* This might be a button release from a transition between mouse messages and raw input. + * See if there's another mouse source that already has that button down and use that. + */ + for (i = 0; i < mouse->num_sources; ++i) { + source = &mouse->sources[i]; + if ((source->buttonstate & SDL_BUTTON_MASK(button))) { + match = source; + break; + } + } + } + if (match) { + return match; + } + + sources = (SDL_MouseInputSource *)SDL_realloc(mouse->sources, (mouse->num_sources + 1) * sizeof(*mouse->sources)); + if (sources) { + mouse->sources = sources; + ++mouse->num_sources; + source = &sources[mouse->num_sources - 1]; + SDL_zerop(source); + source->mouseID = mouseID; + return source; + } } return NULL; } @@ -1080,7 +1084,7 @@ void SDL_QuitMouse(void) SDL_Cursor *cursor, *next; SDL_Mouse *mouse = SDL_GetMouse(); - SDL_mouse_quitting = true; + SDL_mouse_initialized = false; if (mouse->added_mouse_touch_device) { SDL_DelTouch(SDL_MOUSE_TOUCHID); @@ -1181,8 +1185,6 @@ void SDL_QuitMouse(void) mouse->internal = NULL; } SDL_zerop(mouse); - - SDL_mouse_quitting = false; } bool SDL_SetRelativeMouseTransform(SDL_MouseMotionTransformCallback transform, void *userdata)