ChangeSet 1.1315.8.24, 2003/09/17 17:59:40-07:00, [EMAIL PROTECTED]

[PATCH] USB: Changes to core/config.c (5 of 9)

This patch centralizes the error checking for invalid descriptor lengths
and unexpected descriptor types.  Instead of doing it in three different
places -- while parsing configuration, interface, and endpoint descriptors
-- the new code does it all at once.  Not surprisingly, this yields a net
savings in code size.


 drivers/usb/core/config.c |   76 ++++++++++++++++++++++------------------------
 1 files changed, 37 insertions(+), 39 deletions(-)


diff -Nru a/drivers/usb/core/config.c b/drivers/usb/core/config.c
--- a/drivers/usb/core/config.c Fri Sep 19 17:09:44 2003
+++ b/drivers/usb/core/config.c Fri Sep 19 17:09:44 2003
@@ -37,23 +37,15 @@
        buffer += header->bLength;
        size -= header->bLength;
 
-       /* Skip over the rest of the Class Specific or Vendor Specific */
-       /*  descriptors */
+       /* Skip over any Class Specific or Vendor Specific descriptors */
        begin = buffer;
        numskipped = 0;
        while (size >= sizeof(struct usb_descriptor_header)) {
                header = (struct usb_descriptor_header *)buffer;
 
-               if (header->bLength < 2) {
-                       err("invalid descriptor length of %d", header->bLength);
-                       return -EINVAL;
-               }
-
                /* If we find another "proper" descriptor then we're done  */
                if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
-                   (header->bDescriptorType == USB_DT_INTERFACE) ||
-                   (header->bDescriptorType == USB_DT_CONFIG) ||
-                   (header->bDescriptorType == USB_DT_DEVICE))
+                   (header->bDescriptorType == USB_DT_INTERFACE))
                        break;
 
                dbg("skipping descriptor 0x%X", header->bDescriptorType);
@@ -155,27 +147,18 @@
 
                memcpy(&ifp->desc, buffer, USB_DT_INTERFACE_SIZE);
 
-               /* Skip over the interface */
                buffer += ifp->desc.bLength;
                size -= ifp->desc.bLength;
 
+               /* Skip over any Class Specific or Vendor Specific descriptors */
                begin = buffer;
                numskipped = 0;
-
-               /* Skip over any interface, class or vendor descriptors */
                while (size >= sizeof(struct usb_descriptor_header)) {
                        header = (struct usb_descriptor_header *)buffer;
 
-                       if (header->bLength < 2) {
-                               err("invalid descriptor length of %d", 
header->bLength);
-                               return -EINVAL;
-                       }
-
                        /* If we find another "proper" descriptor then we're done  */
                        if ((header->bDescriptorType == USB_DT_INTERFACE) ||
-                           (header->bDescriptorType == USB_DT_ENDPOINT) ||
-                           (header->bDescriptorType == USB_DT_CONFIG) ||
-                           (header->bDescriptorType == USB_DT_DEVICE))
+                           (header->bDescriptorType == USB_DT_ENDPOINT))
                                break;
 
                        dbg("skipping descriptor 0x%X", header->bDescriptorType);
@@ -184,7 +167,6 @@
                        buffer += header->bLength;
                        size -= header->bLength;
                }
-
                if (numskipped) {
                        dbg("skipped %d class/vendor specific interface descriptors", 
numskipped);
 
@@ -201,13 +183,6 @@
                        ifp->extralen = len;
                }
 
-               /* Did we hit an unexpected descriptor? */
-               header = (struct usb_descriptor_header *)buffer;
-               if ((size >= sizeof(struct usb_descriptor_header)) &&
-                   ((header->bDescriptorType == USB_DT_CONFIG) ||
-                    (header->bDescriptorType == USB_DT_DEVICE)))
-                       break;
-
                if (ifp->desc.bNumEndpoints > USB_MAXENDPOINTS) {
                        warn("too many endpoints");
                        return -EINVAL;
@@ -249,11 +224,13 @@
 int usb_parse_configuration(struct usb_host_config *config, char *buffer)
 {
        int nintf;
-       int i, size;
+       int i, j, size;
        struct usb_interface *interface;
+       char *buffer2;
+       int size2;
+       struct usb_descriptor_header *header;
        int numskipped, len;
        char *begin;
-       struct usb_descriptor_header *header;
        int retval;
 
        memcpy(&config->desc, buffer, USB_DT_CONFIG_SIZE);
@@ -283,6 +260,34 @@
                get_device(&interface->dev);
        }
 
+       /* Go through the descriptors, checking their length */
+       buffer2 = buffer;
+       size2 = size;
+       j = 0;
+       while (size2 >= sizeof(struct usb_descriptor_header)) {
+               header = (struct usb_descriptor_header *) buffer2;
+               if ((header->bLength > size2) || (header->bLength < 2)) {
+                       err("invalid descriptor of length %d", header->bLength);
+                       return -EINVAL;
+               }
+
+               if (header->bDescriptorType == USB_DT_INTERFACE) {
+                       if (header->bLength < USB_DT_INTERFACE_SIZE) {
+                               warn("invalid interface descriptor");
+                               return -EINVAL;
+                       }
+
+               } else if ((header->bDescriptorType == USB_DT_DEVICE ||
+                   header->bDescriptorType == USB_DT_CONFIG) && j) {
+                       warn("unexpected descriptor type 0x%X", 
header->bDescriptorType);
+                       return -EINVAL;
+               }
+
+               j = 1;
+               buffer2 += header->bLength;
+               size2 -= header->bLength;
+       }
+
        buffer += config->desc.bLength;
        size -= config->desc.bLength;
 
@@ -292,16 +297,9 @@
        while (size >= sizeof(struct usb_descriptor_header)) {
                header = (struct usb_descriptor_header *)buffer;
 
-               if ((header->bLength > size) || (header->bLength < 2)) {
-                       err("invalid descriptor length of %d", header->bLength);
-                       return -EINVAL;
-               }
-
                /* If we find another "proper" descriptor then we're done  */
                if ((header->bDescriptorType == USB_DT_ENDPOINT) ||
-                   (header->bDescriptorType == USB_DT_INTERFACE) ||
-                   (header->bDescriptorType == USB_DT_CONFIG) ||
-                   (header->bDescriptorType == USB_DT_DEVICE))
+                   (header->bDescriptorType == USB_DT_INTERFACE))
                        break;
 
                dbg("skipping descriptor 0x%X", header->bDescriptorType);



-------------------------------------------------------
This sf.net email is sponsored by:ThinkGeek
Welcome to geek heaven.
http://thinkgeek.com/sf
_______________________________________________
[EMAIL PROTECTED]
To unsubscribe, use the last form field at:
https://lists.sourceforge.net/lists/listinfo/linux-usb-devel

Reply via email to