Don't overrun the changes array when synching > MAX_SLOTS
authorPeter Hutterer <peter.hutterer@who-t.net>
Thu, 5 Mar 2020 03:37:46 +0000 (13:37 +1000)
committerPeter Hutterer <peter.hutterer@who-t.net>
Fri, 13 Mar 2020 04:07:25 +0000 (14:07 +1000)
On a device with more than 256 slots we would read (and copy) past our changes
stack-allocated changes array. Fix this by capping to MAX_SLOTS though this
also requires us to memset the target where it is larger than MAX_SLOTS.

There are no real devices with 256+ slots, so this is a theoretical issue
only.

Fixes #11

Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
libevdev/libevdev.c

index f034637ef48f1ffb96d48dc58edea71c87801bc0..f7543e0dd0e53557455714185ecaa6b8333c8d45 100644 (file)
@@ -680,6 +680,7 @@ sync_mt_state(struct libevdev *dev,
 #define MAX_SLOTS 256
        int rc = 0;
        struct slot_change_state changes[MAX_SLOTS] = {0};
+       unsigned int nslots = min(MAX_SLOTS, dev->num_slots);
 
        for (int axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
                /* EVIOCGMTSLOTS required format */
@@ -697,7 +698,7 @@ sync_mt_state(struct libevdev *dev,
                if (rc < 0)
                        goto out;
 
-               for (int slot = 0; slot < min(MAX_SLOTS, dev->num_slots); slot++) {
+               for (unsigned int slot = 0; slot < nslots; slot++) {
                        int val_before = *slot_value(dev, slot, axis),
                            val_after = mt_state.val[slot];
 
@@ -728,7 +729,10 @@ sync_mt_state(struct libevdev *dev,
                }
        }
 
-       memcpy(changes_out, changes, sizeof(*changes) * dev->num_slots);
+       if (dev->num_slots > MAX_SLOTS)
+               memset(changes_out, 0, sizeof(*changes) * dev->num_slots);
+
+       memcpy(changes_out, changes, sizeof(*changes) * nslots);
 out:
        return rc;
 }