chiark / gitweb /
hostside/usbhid: cope when the device sends a field beyond maxusage
authorIan Jackson <ian@liberator.relativity.greenend.org.uk>
Fri, 14 Jan 2011 00:00:34 +0000 (00:00 +0000)
committerIan Jackson <ian@liberator.relativity.greenend.org.uk>
Fri, 14 Jan 2011 00:00:34 +0000 (00:00 +0000)
hostside/evdev-manip.c

index 0a128b53cc6030e33cf8b6ddf8f37677af4514fe..72d52ee8f580688c07b6c2b4192a9144c598b230 100644 (file)
@@ -63,6 +63,7 @@
 #include <poll.h>
 #include <sys/fcntl.h>
 #include <search.h>
+#include <inttypes.h>
 
 #include <linux/input.h>
 #include <linux/hiddev.h>
@@ -109,6 +110,7 @@ typedef struct {
 
 typedef struct {
   struct hiddev_field_info fi;
+  uint32_t maxusage;
   int *lastvalues;
 } HiddevField;
 
@@ -372,11 +374,21 @@ static HiddevField *hiddev_get_f(Device *d,
     if (r) diee("%s: ioctl HIDIOCGFIELDINFO %#x %#x %#x", d->path,
                f->fi.report_type, f->fi.report_id, f->fi.field_index);
 
-    size_t sz= sizeof(*f->lastvalues) * f->fi.maxusage;
+    f->maxusage= f->fi.maxusage;
+
+    size_t sz= sizeof(*f->lastvalues) * f->maxusage;
     f->lastvalues= mmalloc(sz);
     memset(f->lastvalues,0,sz);
   }
-  assert(ur->usage_index < f->fi.maxusage);
+  if (ur->usage_index >= f->maxusage) {
+    uint32_t newmax= ur->usage_index + 1;
+    fprintf(stderr,"%s: usage_index %"PRIu32" >= maxusage %"PRIu32"\n",
+           d->path, ur->usage_index, f->maxusage);
+    f->lastvalues= mrealloc(f->lastvalues, sizeof(*f->lastvalues) * newmax);
+    memset(f->lastvalues + f->maxusage, 0,
+          sizeof(*f->lastvalues) * (newmax - f->maxusage));
+    f->maxusage= newmax;
+  }
 
   return f;
 }