[PATCH] Fix FOO_MAX off-by-one

Peter Hutterer peter.hutterer at who-t.net
Sun Jan 11 19:29:55 PST 2009


On Sun, Jan 11, 2009 at 06:36:59PM -0800, Matt Helsley wrote:
> 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.
> 

Pushed as 4dfd86b2201b2b19761a1abb3c580cecf0060224, thanks.


> 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