56 lines
2.4 KiB
Diff
56 lines
2.4 KiB
Diff
# UNDF: UNDF-2026-000000751
|
|
# UNDF: (leave blank)
|
|
SDL CWE-407: SDL_PrivateAddMappingForGUID — O(M) tail walk when inserting each mapping → O(M²) bulk load
|
|
|
|
The s_pSupportedGamepads linked list has no tail pointer. Every new mapping
|
|
insertion walks the entire list from head to tail (SDL_gamepad.c:2213-2217)
|
|
just to find the insertion point. Loading M mappings therefore costs O(M²).
|
|
|
|
The SDL_GameControllerDB community database ships >30 000 entries. At M=30 000,
|
|
the tail walk alone performs ~450 000 000 pointer dereferences at startup.
|
|
|
|
Additionally, SDL_PrivateGetGamepadMappingForGUID (called once per insert for
|
|
dedup) performs its own O(M) linked-list scan, contributing another O(M²) term.
|
|
|
|
Severity: MEDIUM — startup latency; proportional to community DB size.
|
|
Complexity: O(M²) → O(M) with a tail pointer + hash-table dedup.
|
|
|
|
--- a/src/joystick/SDL_gamepad.c
|
|
+++ b/src/joystick/SDL_gamepad.c
|
|
|
|
@@ DEFECT sdl-0001: tail walk on s_pSupportedGamepads @@
|
|
|
|
static SDL_GUID s_zeroGUID;
|
|
static GamepadMapping_t *s_pSupportedGamepads SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
|
+/* FIX sdl-0001: track list tail to avoid O(M) walk on every append */
|
|
+static GamepadMapping_t *s_pLastSupportedGamepad SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
|
static GamepadMapping_t *s_pDefaultMapping SDL_GUARDED_BY(SDL_joystick_lock) = NULL;
|
|
|
|
@@ SDL_PrivateAddMappingForGUID — replace tail walk with O(1) tail pointer @@
|
|
|
|
- if (s_pSupportedGamepads) {
|
|
- // Add the mapping to the end of the list
|
|
- GamepadMapping_t *pCurrMapping, *pPrevMapping;
|
|
-
|
|
- for (pPrevMapping = s_pSupportedGamepads, pCurrMapping = pPrevMapping->next;
|
|
- pCurrMapping;
|
|
- pPrevMapping = pCurrMapping, pCurrMapping = pCurrMapping->next) {
|
|
- // continue;
|
|
- }
|
|
- pPrevMapping->next = pGamepadMapping;
|
|
- } else {
|
|
- s_pSupportedGamepads = pGamepadMapping;
|
|
- }
|
|
+ /* FIX sdl-0001: O(1) append via tail pointer */
|
|
+ if (s_pLastSupportedGamepad) {
|
|
+ s_pLastSupportedGamepad->next = pGamepadMapping;
|
|
+ } else {
|
|
+ s_pSupportedGamepads = pGamepadMapping;
|
|
+ }
|
|
+ s_pLastSupportedGamepad = pGamepadMapping;
|
|
|
|
@@ SDL_QuitGamepadMappings (or wherever s_pSupportedGamepads is reset to NULL) @@
|
|
|
|
- s_pSupportedGamepads = NULL;
|
|
+ s_pSupportedGamepads = NULL;
|
|
+ s_pLastSupportedGamepad = NULL; /* FIX sdl-0001: reset tail pointer */
|