From 615c7efd98e010da16f156300e70a57f324e0ed5 Mon Sep 17 00:00:00 2001 From: Christoph Reichenbach Date: Mon, 18 Mar 2024 08:40:23 +0000 Subject: [PATCH] Fix #9279: Memory leak in pen name handling - Fixes a leak in pen name allocation that would trigger for both X11 and Wayland for some non-pen input devices when new devices are added/removed. - SDL_PenQuit() now deallocates and resets the table of known pens - testautomation_pen.c now uses PenInit and PenQuit as setup and teardown, respectively testautomation_pen.c was already triggering the leak, and it is visible with --trackmem, so no new tests are added. --- src/events/SDL_pen.c | 14 +++++++++++++- test/testautomation_pen.c | 22 +++++++++++++++++----- 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/events/SDL_pen.c b/src/events/SDL_pen.c index e2eb4e10cf..d0b02a5631 100644 --- a/src/events/SDL_pen.c +++ b/src/events/SDL_pen.c @@ -269,7 +269,7 @@ static void pen_sort(void) pen_compare); pen_handler.sorted = SDL_TRUE; } - +#include SDL_Pen *SDL_PenModifyBegin(Uint32 instance_id) { SDL_PenID id = { 0 }; @@ -357,6 +357,7 @@ void SDL_PenModifyEnd(SDL_Pen *pen, SDL_bool attach) attach = SDL_FALSE; } else { pen_handler.pens_known -= 1; + SDL_free(pen->name); SDL_memset(pen, 0, sizeof(SDL_Pen)); SDL_UNLOCK_PENS(); return; @@ -828,6 +829,8 @@ void SDL_PenInit(void) void SDL_PenQuit(void) { + unsigned int i; + SDL_DelHintCallback(SDL_HINT_PEN_NOT_MOUSE, SDL_PenUpdateHint, &pen_mouse_emulation_mode); @@ -837,6 +840,15 @@ void SDL_PenQuit(void) SDL_DestroyMutex(SDL_pen_access_lock); SDL_pen_access_lock = NULL; #endif + + if (pen_handler.pens) { + for (i = 0; i < pen_handler.pens_known; ++i) { + SDL_free(pen_handler.pens[i].name); + } + SDL_free(pen_handler.pens); + /* Reset static pen information */ + SDL_memset(&pen_handler, 0, sizeof(pen_handler)); + } } SDL_bool SDL_PenPerformHitTest(void) diff --git a/test/testautomation_pen.c b/test/testautomation_pen.c index 7bbc5aa370..445a298dff 100644 --- a/test/testautomation_pen.c +++ b/test/testautomation_pen.c @@ -1872,9 +1872,21 @@ pen_memoryLayout(void *arg) return TEST_COMPLETED; } +/* ================= Test Setup and Teardown ================== */ + +static void +pen_test_setup(void *arg) { + SDL_PenInit(); +} + +static void +pen_test_teardown(void *arg) { + SDL_PenQuit(); +} + /* ================= Test References ================== */ -/* Mouse test cases */ +/* Pen test cases */ static const SDLTest_TestCaseReference penTest1 = { (SDLTest_TestCaseFp)pen_iteration, "pen_iteration", "Iterate over all pens with SDL_PenIDForIndex", TEST_ENABLED }; static const SDLTest_TestCaseReference penTest2 = { (SDLTest_TestCaseFp)pen_hotplugging, "pen_hotplugging", "Hotplug pens and validate their status, including SDL_PenConnected", TEST_ENABLED }; @@ -1893,17 +1905,17 @@ static const SDLTest_TestCaseReference penTest8 = { (SDLTest_TestCaseFp)pen_mous static const SDLTest_TestCaseReference penTest9 = { (SDLTest_TestCaseFp)pen_memoryLayout, "pen_memoryLayout", "Check that all pen events have compatible layout (required by SDL_pen.c)", TEST_ENABLED }; -/* Sequence of Mouse test cases */ +/* Sequence of Pen test cases */ static const SDLTest_TestCaseReference *penTests[] = { &penTest1, &penTest2, &penTest3, &penTest4, &penTest5, &penTest6, &penTest7, &penTest8, &penTest9, NULL }; -/* Mouse test suite (global) */ +/* Pen test suite (global) */ SDLTest_TestSuiteReference penTestSuite = { "Pen", - NULL, + (SDLTest_TestCaseSetUpFp)pen_test_setup, penTests, - NULL + (SDLTest_TestCaseTearDownFp)pen_test_teardown }; #else