[PATCH] Fix FOO_MAX off-by-one

Matt Helsley matt.helsley at gmail.com
Sun Jan 11 18:36:59 PST 2009


In linux/input.h each section's (e.g. ABS) FOO_MAX is the maximum FOO
value. Recent kernels define FOO_CNT as the maximum number of FOO there
will ever be. Hence using FOO_MAX to size the bit vectors representing
the capabilities of an evdev device is off by one.

Define FOO_CNT values for use with Linux kernels which lack them. Use
FOO_CNT whenever we need to know the number of bits needed -- usually to
calculate the number of longs needed.

When iterating over the values FOO_MAX still seems appropriate however
the loop test should include FOO_MAX rather than skip it.

Signed-off-by: Matt Helsley <matt.helsley at gmail.com>
---
 src/evdev.c |   24 ++++++++++++------------
 src/evdev.h |   28 ++++++++++++++++++++++------
 2 files changed, 34 insertions(+), 18 deletions(-)

Index: xf86-input-evdev/src/evdev.c
===================================================================
--- xf86-input-evdev.orig/src/evdev.c
+++ xf86-input-evdev/src/evdev.c
@@ -234,18 +234,18 @@ PostButtonClicks(InputInfoPtr pInfo, int
 
 static void
 PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
 {
     int code = ev->code + MIN_KEYCODE;
-    static char warned[KEY_MAX];
+    static char warned[KEY_CNT];
 
     /* Filter all repeated events from device.
        We'll do softrepeat in the server */
     if (value == 2)
 	return;
 
-    if (code > 255 && ev->code < KEY_MAX) {
+    if (code > 255 && ev->code <= KEY_MAX) {
 	if (!warned[ev->code])
 	    xf86Msg(X_WARNING, "%s: unable to handle keycode %d\n",
 		    pInfo->name, ev->code);
 	warned[ev->code] = 1;
     }
@@ -1221,16 +1221,16 @@ EvdevCacheCompare(InputInfoPtr pInfo, BO
 {
     EvdevPtr pEvdev = pInfo->private;
     int i;
 
     char name[1024]                  = {0};
-    long bitmask[NLONGS(EV_MAX)]      = {0};
-    long key_bitmask[NLONGS(KEY_MAX)] = {0};
-    long rel_bitmask[NLONGS(REL_MAX)] = {0};
-    long abs_bitmask[NLONGS(ABS_MAX)] = {0};
-    long led_bitmask[NLONGS(LED_MAX)] = {0};
-    struct input_absinfo absinfo[ABS_MAX];
+    long bitmask[NLONGS(EV_CNT)]      = {0};
+    long key_bitmask[NLONGS(KEY_CNT)] = {0};
+    long rel_bitmask[NLONGS(REL_CNT)] = {0};
+    long abs_bitmask[NLONGS(ABS_CNT)] = {0};
+    long led_bitmask[NLONGS(LED_CNT)] = {0};
+    struct input_absinfo absinfo[ABS_CNT];
 
     if (ioctl(pInfo->fd,
               EVIOCGNAME(sizeof(name) - 1), name) < 0) {
         xf86Msg(X_ERROR, "ioctl EVIOCGNAME failed: %s\n", strerror(errno));
         goto error;
@@ -1285,11 +1285,11 @@ EvdevCacheCompare(InputInfoPtr pInfo, BO
     if (compare && memcmp(pEvdev->led_bitmask, led_bitmask, sizeof(led_bitmask)))
         goto error;
 
     memset(absinfo, 0, sizeof(absinfo));
 
-    for (i = 0; i < ABS_MAX; i++)
+    for (i = ABS_X; i <= ABS_MAX; i++)
     {
         if (TestBit(i, abs_bitmask))
         {
             if (ioctl(pInfo->fd, EVIOCGABS(i), &absinfo[i]) < 0) {
                 xf86Msg(X_ERROR, "ioctl EVIOCGABS failed: %s\n", strerror(errno));
@@ -1321,13 +1321,13 @@ error:
 }
 
 static int
 EvdevProbe(InputInfoPtr pInfo)
 {
-    long key_bitmask[NLONGS(KEY_MAX)] = {0};
-    long rel_bitmask[NLONGS(REL_MAX)] = {0};
-    long abs_bitmask[NLONGS(ABS_MAX)] = {0};
+    long key_bitmask[NLONGS(KEY_CNT)] = {0};
+    long rel_bitmask[NLONGS(REL_CNT)] = {0};
+    long abs_bitmask[NLONGS(ABS_CNT)] = {0};
     int i, has_axes, has_keys, num_buttons, has_scroll;
     int kernel24 = 0;
     EvdevPtr pEvdev = pInfo->private;
 
     if (pEvdev->grabDevice && ioctl(pInfo->fd, EVIOCGRAB, (void *)1)) {
Index: xf86-input-evdev/src/evdev.h
===================================================================
--- xf86-input-evdev.orig/src/evdev.h
+++ xf86-input-evdev/src/evdev.h
@@ -38,10 +38,26 @@
 
 #ifdef XKB
 #include <xkbstr.h>
 #endif
 
+#ifndef EV_CNT /* linux 2.4 kernels and earlier lack _CNT defines */
+#define EV_CNT (EV_MAX+1)
+#endif
+#ifndef KEY_CNT
+#define KEY_CNT (KEY_MAX+1)
+#endif
+#ifndef REL_CNT
+#define REL_CNT (REL_MAX+1)
+#endif
+#ifndef ABS_CNT
+#define ABS_CNT (ABS_MAX+1)
+#endif
+#ifndef LED_CNT
+#define LED_CNT (LED_MAX+1)
+#endif
+
 #define EVDEV_MAXBUTTONS 32
 
 #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
 #define HAVE_PROPERTIES 1
 #endif
@@ -121,16 +137,16 @@ typedef struct {
     int reopen_left;     /* number of attempts left to re-open the device */
     OsTimerPtr reopen_timer;
 
     /* Cached info from device. */
     char name[1024];
-    long bitmask[NLONGS(EV_MAX)];
-    long key_bitmask[NLONGS(KEY_MAX)];
-    long rel_bitmask[NLONGS(REL_MAX)];
-    long abs_bitmask[NLONGS(ABS_MAX)];
-    long led_bitmask[NLONGS(LED_MAX)];
-    struct input_absinfo absinfo[ABS_MAX];
+    long bitmask[NLONGS(EV_CNT)];
+    long key_bitmask[NLONGS(KEY_CNT)];
+    long rel_bitmask[NLONGS(REL_CNT)];
+    long abs_bitmask[NLONGS(ABS_CNT)];
+    long led_bitmask[NLONGS(LED_CNT)];
+    struct input_absinfo absinfo[ABS_CNT];
 
     /* minor/major number */
     dev_t min_maj;
 } EvdevRec, *EvdevPtr;
 





More information about the xorg mailing list