Fix joystick device add events containing invalid device indexes

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.
This commit is contained in:
Cameron Gutman 2020-08-29 16:50:26 -07:00
parent 7854f43b6d
commit 9d40a0f317
2 changed files with 36 additions and 6 deletions

View File

@ -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;
@ -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);
@ -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;
@ -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;

View File

@ -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;
@ -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);
@ -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
@ -1265,7 +1281,7 @@ void SDL_PrivateJoystickRemoved(SDL_JoystickID device_instance)
SDL_PushEvent(&event);
}
UpdateEventsForDeviceRemoval();
UpdateEventsForDeviceRemoval(device_index);
#endif /* !SDL_EVENTS_DISABLED */
SDL_LockJoysticks();