summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2013-05-23 15:20:12 +0200
committerHans de Goede <hdegoede@redhat.com>2013-05-24 13:58:37 +0200
commit25b314279a6774198cf6de4170c76f458ebc89a2 (patch)
tree8925cae0419b8560e8f84e54acbf5089bc2e8c10
parentbbe25fac47c2dfd2d50a2c3a1b0ed96473d8dc1c (diff)
downloadlibusb-25b314279a6774198cf6de4170c76f458ebc89a2.tar.gz
descriptor.c: Read a full config-desc-header on first config-desc read
For some reason the first get config call to determine the total-length was only reading 8 of the 9 bytes of a full config-desc-header, which is weird. The Linux kernel reads the full 9 on the first call, so lets do that in libusb too. Note that for backends which cache the config this does not matter. Also check that we've actually gotten back a full header, before parsing it. Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--libusb/descriptor.c28
-rw-r--r--libusb/version_nano.h2
2 files changed, 24 insertions, 6 deletions
diff --git a/libusb/descriptor.c b/libusb/descriptor.c
index 74d3365..7913254 100644
--- a/libusb/descriptor.c
+++ b/libusb/descriptor.c
@@ -346,6 +346,12 @@ static int parse_configuration(struct libusb_context *ctx,
struct usb_descriptor_header header;
struct libusb_interface *usb_interface;
+ if (size < LIBUSB_DT_CONFIG_SIZE) {
+ usbi_err(ctx, "short config descriptor read %d/%d",
+ size, LIBUSB_DT_CONFIG_SIZE);
+ return LIBUSB_ERROR_IO;
+ }
+
usbi_parse_descriptor(buffer, "bbwbbbbb", config, host_endian);
if (config->bNumInterfaces > USB_MAXINTERFACES) {
@@ -491,7 +497,7 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
struct libusb_config_descriptor **config)
{
struct libusb_config_descriptor *_config = malloc(sizeof(*_config));
- unsigned char tmp[8];
+ unsigned char tmp[LIBUSB_DT_CONFIG_SIZE];
unsigned char *buf = NULL;
int host_endian = 0;
int r;
@@ -500,10 +506,16 @@ int API_EXPORTED libusb_get_active_config_descriptor(libusb_device *dev,
if (!_config)
return LIBUSB_ERROR_NO_MEM;
- r = usbi_backend->get_active_config_descriptor(dev, tmp, sizeof(tmp),
- &host_endian);
+ r = usbi_backend->get_active_config_descriptor(dev, tmp,
+ LIBUSB_DT_CONFIG_SIZE, &host_endian);
if (r < 0)
goto err;
+ if (r < LIBUSB_DT_CONFIG_SIZE) {
+ usbi_err(dev->ctx, "short config descriptor read %d/%d",
+ r, LIBUSB_DT_CONFIG_SIZE);
+ r = LIBUSB_ERROR_IO;
+ goto err;
+ }
_config->wTotalLength = 0;
usbi_parse_descriptor(tmp, "bbw", _config, host_endian);
@@ -558,7 +570,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
uint8_t config_index, struct libusb_config_descriptor **config)
{
struct libusb_config_descriptor *_config;
- unsigned char tmp[8];
+ unsigned char tmp[LIBUSB_DT_CONFIG_SIZE];
unsigned char *buf = NULL;
int host_endian = 0;
int r;
@@ -572,9 +584,15 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
return LIBUSB_ERROR_NO_MEM;
r = usbi_backend->get_config_descriptor(dev, config_index, tmp,
- sizeof(tmp), &host_endian);
+ LIBUSB_DT_CONFIG_SIZE, &host_endian);
if (r < 0)
goto err;
+ if (r < LIBUSB_DT_CONFIG_SIZE) {
+ usbi_err(dev->ctx, "short config descriptor read %d/%d",
+ r, LIBUSB_DT_CONFIG_SIZE);
+ r = LIBUSB_ERROR_IO;
+ goto err;
+ }
usbi_parse_descriptor(tmp, "bbw", _config, host_endian);
buf = malloc(_config->wTotalLength);
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 8f8d647..6853e9a 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 10710
+#define LIBUSB_NANO 10711