Skip to content

Commit

Permalink
Fix joystick device add events containing invalid device indexes
Browse files Browse the repository at this point in the history
This can happen if the application has not yet processed SDL_JOYDEVICEADD when
the same joystick is removed. It may also happen if two joysticks are added
and the second joystick is removed before the first joystick's SDL_JOYDEVICEADD
has been processed by the application.
  • Loading branch information
cgutman committed Aug 29, 2020
1 parent 7854f43 commit 9d40a0f
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 6 deletions.
20 changes: 17 additions & 3 deletions src/joystick/SDL_gamecontroller.c
Expand Up @@ -202,7 +202,7 @@ static int SDL_PrivateGameControllerButton(SDL_GameController *gamecontroller, S
* to have the right value for which, because the number of controllers in
* the system is now one less.
*/
static void UpdateEventsForDeviceRemoval()
static void UpdateEventsForDeviceRemoval(int device_index)
{
int i, num_events;
SDL_Event *events;
Expand All @@ -220,7 +220,19 @@ static void UpdateEventsForDeviceRemoval()

num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_CONTROLLERDEVICEADDED, SDL_CONTROLLERDEVICEADDED);
for (i = 0; i < num_events; ++i) {
--events[i].cdevice.which;
if (events[i].cdevice.which < device_index) {
/* No change for index values lower than the removed device */
}
else if (events[i].cdevice.which == device_index) {
/* Drop this event entirely */
SDL_memmove(&events[i], &events[i + 1], sizeof(*events) * (num_events - (i + 1)));
--i;
--num_events;
}
else {
/* Fix up the device index if greater than the removed device */
--events[i].cdevice.which;
}
}
SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);

Expand Down Expand Up @@ -427,6 +439,7 @@ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event * ev
case SDL_JOYDEVICEREMOVED:
{
SDL_GameController *controllerlist = SDL_gamecontrollers;
int device_index = 0;
while (controllerlist) {
if (controllerlist->joystick->instance_id == event->jdevice.which) {
SDL_Event deviceevent;
Expand All @@ -437,10 +450,11 @@ static int SDLCALL SDL_GameControllerEventWatcher(void *userdata, SDL_Event * ev
deviceevent.cdevice.which = event->jdevice.which;
SDL_PushEvent(&deviceevent);

UpdateEventsForDeviceRemoval();
UpdateEventsForDeviceRemoval(device_index);
break;
}
controllerlist = controllerlist->next;
++device_index;
}
}
break;
Expand Down
22 changes: 19 additions & 3 deletions src/joystick/SDL_joystick.c
Expand Up @@ -1184,7 +1184,7 @@ void SDL_PrivateJoystickAdded(SDL_JoystickID device_instance)
* to have the right value for which, because the number of controllers in
* the system is now one less.
*/
static void UpdateEventsForDeviceRemoval()
static void UpdateEventsForDeviceRemoval(int device_index)
{
int i, num_events;
SDL_Event *events;
Expand All @@ -1202,7 +1202,19 @@ static void UpdateEventsForDeviceRemoval()

num_events = SDL_PeepEvents(events, num_events, SDL_GETEVENT, SDL_JOYDEVICEADDED, SDL_JOYDEVICEADDED);
for (i = 0; i < num_events; ++i) {
--events[i].jdevice.which;
if (events[i].cdevice.which < device_index) {
/* No change for index values lower than the removed device */
}
else if (events[i].cdevice.which == device_index) {
/* Drop this event entirely */
SDL_memmove(&events[i], &events[i + 1], sizeof(*events) * (num_events - (i + 1)));
--num_events;
--i;
}
else {
/* Fix up the device index if greater than the removed device */
--events[i].cdevice.which;
}
}
SDL_PeepEvents(events, num_events, SDL_ADDEVENT, 0, 0);

Expand Down Expand Up @@ -1243,17 +1255,21 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
{
SDL_Joystick *joystick = NULL;
int player_index;
int device_index;
#if !SDL_EVENTS_DISABLED
SDL_Event event;
#endif

/* Find this joystick... */
device_index = 0;
for (joystick = SDL_joysticks; joystick; joystick = joystick->next) {
if (joystick->instance_id == device_instance) {
SDL_PrivateJoystickForceRecentering(joystick);
joystick->attached = SDL_FALSE;
break;
}

++device_index;
}

#if !SDL_EVENTS_DISABLED
Expand All @@ -1265,7 +1281,7 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
SDL_PushEvent(&event);
}

UpdateEventsForDeviceRemoval();
UpdateEventsForDeviceRemoval(device_index);
#endif /* !SDL_EVENTS_DISABLED */

SDL_LockJoysticks();
Expand Down

0 comments on commit 9d40a0f

Please sign in to comment.