diff options
author | Hans de Goede <hdegoede@redhat.com> | 2013-05-23 15:20:12 +0200 |
---|---|---|
committer | Hans de Goede <hdegoede@redhat.com> | 2013-05-24 13:58:37 +0200 |
commit | 25b314279a6774198cf6de4170c76f458ebc89a2 (patch) | |
tree | 8925cae0419b8560e8f84e54acbf5089bc2e8c10 | |
parent | bbe25fac47c2dfd2d50a2c3a1b0ed96473d8dc1c (diff) | |
download | libusb-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.c | 28 | ||||
-rw-r--r-- | libusb/version_nano.h | 2 |
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 |