summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Dickens <christopher.a.dickens@gmail.com>2020-03-16 01:01:51 -0700
committerChris Dickens <christopher.a.dickens@gmail.com>2020-03-16 01:01:51 -0700
commit15bd82e9a2935fd4e5c1a9ed83c73d364e92d8ec (patch)
treedd1c590d17a0f10adfe9ca98b18b7783de3e3efc
parent26b16eb65a61b37b64ce8962b5b7d927c3c54a7d (diff)
downloadlibusb-15bd82e9a2935fd4e5c1a9ed83c73d364e92d8ec.tar.gz
core: Move parameter validation from backend to core
Some functions (e.g. libusb_set_interface_alt_setting()) do not perform sufficient parameter validation, leaving the burden on the backend to catch invalid user input. Much of this validation is common across all backends, yet not every backend implemented it. Fix this by moving parameter validation to the core library functions. This is also a good opportunity to remove the redundant 'num_configurations' field from the libusb_device structure. The value of this field is already contained in the 'device_descriptor' member. Signed-off-by: Chris Dickens <christopher.a.dickens@gmail.com>
-rw-r--r--libusb/core.c31
-rw-r--r--libusb/descriptor.c4
-rw-r--r--libusb/io.c2
-rw-r--r--libusb/libusbi.h3
-rw-r--r--libusb/os/haiku_usb_raw.cpp2
-rw-r--r--libusb/os/sunos_usb.c13
-rw-r--r--libusb/os/windows_usbdk.c6
-rw-r--r--libusb/os/windows_winusb.c36
-rw-r--r--libusb/os/windows_winusb.h4
-rw-r--r--libusb/version_nano.h2
10 files changed, 48 insertions, 55 deletions
diff --git a/libusb/core.c b/libusb/core.c
index 85d62e4..7ffec1f 100644
--- a/libusb/core.c
+++ b/libusb/core.c
@@ -746,10 +746,10 @@ int usbi_sanitize_device(struct libusb_device *dev)
if (num_configurations > USB_MAXCONFIG) {
usbi_err(DEVICE_CTX(dev), "too many configurations");
return LIBUSB_ERROR_IO;
- } else if (0 == num_configurations)
+ } else if (0 == num_configurations) {
usbi_dbg("zero configurations, maybe an unauthorized device");
+ }
- dev->num_configurations = num_configurations;
return 0;
}
@@ -1636,6 +1636,8 @@ int API_EXPORTED libusb_set_configuration(libusb_device_handle *dev_handle,
int configuration)
{
usbi_dbg("configuration %d", configuration);
+ if (configuration < -1 || configuration > UINT8_MAX)
+ return LIBUSB_ERROR_INVALID_PARAM;
return usbi_backend.set_configuration(dev_handle, configuration);
}
@@ -1673,7 +1675,7 @@ int API_EXPORTED libusb_claim_interface(libusb_device_handle *dev_handle,
int r = 0;
usbi_dbg("interface %d", interface_number);
- if (interface_number >= USB_MAXINTERFACES)
+ if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
return LIBUSB_ERROR_INVALID_PARAM;
if (!dev_handle->dev->attached)
@@ -1717,7 +1719,7 @@ int API_EXPORTED libusb_release_interface(libusb_device_handle *dev_handle,
int r;
usbi_dbg("interface %d", interface_number);
- if (interface_number >= USB_MAXINTERFACES)
+ if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
return LIBUSB_ERROR_INVALID_PARAM;
usbi_mutex_lock(&dev_handle->lock);
@@ -1761,7 +1763,9 @@ int API_EXPORTED libusb_set_interface_alt_setting(libusb_device_handle *dev_hand
{
usbi_dbg("interface %d altsetting %d",
interface_number, alternate_setting);
- if (interface_number >= USB_MAXINTERFACES)
+ if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
+ return LIBUSB_ERROR_INVALID_PARAM;
+ if (alternate_setting < 0 || alternate_setting > UINT8_MAX)
return LIBUSB_ERROR_INVALID_PARAM;
usbi_mutex_lock(&dev_handle->lock);
@@ -1858,7 +1862,10 @@ int API_EXPORTED libusb_reset_device(libusb_device_handle *dev_handle)
int API_EXPORTED libusb_alloc_streams(libusb_device_handle *dev_handle,
uint32_t num_streams, unsigned char *endpoints, int num_endpoints)
{
- usbi_dbg("streams %u eps %d", (unsigned) num_streams, num_endpoints);
+ usbi_dbg("streams %u eps %d", (unsigned)num_streams, num_endpoints);
+
+ if (!num_streams || !endpoints || num_endpoints <= 0)
+ return LIBUSB_ERROR_INVALID_PARAM;
if (!dev_handle->dev->attached)
return LIBUSB_ERROR_NO_DEVICE;
@@ -1887,6 +1894,9 @@ int API_EXPORTED libusb_free_streams(libusb_device_handle *dev_handle,
{
usbi_dbg("eps %d", num_endpoints);
+ if (!endpoints || num_endpoints <= 0)
+ return LIBUSB_ERROR_INVALID_PARAM;
+
if (!dev_handle->dev->attached)
return LIBUSB_ERROR_NO_DEVICE;
@@ -1973,6 +1983,9 @@ int API_EXPORTED libusb_kernel_driver_active(libusb_device_handle *dev_handle,
{
usbi_dbg("interface %d", interface_number);
+ if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
+ return LIBUSB_ERROR_INVALID_PARAM;
+
if (!dev_handle->dev->attached)
return LIBUSB_ERROR_NO_DEVICE;
@@ -2008,6 +2021,9 @@ int API_EXPORTED libusb_detach_kernel_driver(libusb_device_handle *dev_handle,
{
usbi_dbg("interface %d", interface_number);
+ if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
+ return LIBUSB_ERROR_INVALID_PARAM;
+
if (!dev_handle->dev->attached)
return LIBUSB_ERROR_NO_DEVICE;
@@ -2042,6 +2058,9 @@ int API_EXPORTED libusb_attach_kernel_driver(libusb_device_handle *dev_handle,
{
usbi_dbg("interface %d", interface_number);
+ if (interface_number < 0 || interface_number >= USB_MAXINTERFACES)
+ return LIBUSB_ERROR_INVALID_PARAM;
+
if (!dev_handle->dev->attached)
return LIBUSB_ERROR_NO_DEVICE;
diff --git a/libusb/descriptor.c b/libusb/descriptor.c
index 4c7733d..44237dd 100644
--- a/libusb/descriptor.c
+++ b/libusb/descriptor.c
@@ -617,7 +617,7 @@ int API_EXPORTED libusb_get_config_descriptor(libusb_device *dev,
int r;
usbi_dbg("index %d", config_index);
- if (config_index >= dev->num_configurations)
+ if (config_index >= dev->device_descriptor.bNumConfigurations)
return LIBUSB_ERROR_NOT_FOUND;
r = usbi_backend.get_config_descriptor(dev, config_index, tmp,
@@ -655,7 +655,7 @@ int usbi_get_config_index_by_value(struct libusb_device *dev,
uint8_t i;
usbi_dbg("value %d", bConfigurationValue);
- for (i = 0; i < dev->num_configurations; i++) {
+ for (i = 0; i < dev->device_descriptor.bNumConfigurations; i++) {
unsigned char tmp[6];
int host_endian;
int r = usbi_backend.get_config_descriptor(dev, i, tmp, sizeof(tmp),
diff --git a/libusb/io.c b/libusb/io.c
index b843d4a..09ccc83 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -1261,6 +1261,8 @@ struct libusb_transfer * LIBUSB_CALL libusb_alloc_transfer(
struct libusb_transfer *transfer;
assert(iso_packets >= 0);
+ if (iso_packets < 0)
+ return NULL;
priv_size = PTR_ALIGN(usbi_backend.transfer_priv_size);
alloc_size = priv_size
diff --git a/libusb/libusbi.h b/libusb/libusbi.h
index faaeff3..1fdfc84 100644
--- a/libusb/libusbi.h
+++ b/libusb/libusbi.h
@@ -429,12 +429,11 @@ struct libusb_device {
int refcnt;
struct libusb_context *ctx;
+ struct libusb_device *parent_dev;
uint8_t bus_number;
uint8_t port_number;
- struct libusb_device* parent_dev;
uint8_t device_address;
- uint8_t num_configurations;
enum libusb_speed speed;
struct list_head list;
diff --git a/libusb/os/haiku_usb_raw.cpp b/libusb/os/haiku_usb_raw.cpp
index 3162371..63efc17 100644
--- a/libusb/os/haiku_usb_raw.cpp
+++ b/libusb/os/haiku_usb_raw.cpp
@@ -97,7 +97,7 @@ haiku_get_config_descriptor(struct libusb_device *device, uint8_t config_index,
const usb_configuration_descriptor *config = dev->ConfigurationDescriptor(config_index);
if (config == NULL) {
usbi_err(DEVICE_CTX(device), "failed getting configuration descriptor");
- return LIBUSB_ERROR_INVALID_PARAM;
+ return LIBUSB_ERROR_IO;
}
if (len > config->total_length) {
len = config->total_length;
diff --git a/libusb/os/sunos_usb.c b/libusb/os/sunos_usb.c
index 8d0c812..cd32f8b 100644
--- a/libusb/os/sunos_usb.c
+++ b/libusb/os/sunos_usb.c
@@ -1109,8 +1109,8 @@ sunos_set_configuration(struct libusb_device_handle *handle, int config)
if (dpriv->ugenpath == NULL)
return (LIBUSB_ERROR_NOT_SUPPORTED);
- if (config < 1 || config > dpriv->dev_descr.bNumConfigurations)
- return (LIBUSB_ERROR_INVALID_PARAM);
+ if (config < 1)
+ return (LIBUSB_ERROR_NOT_SUPPORTED);
dpriv->cfgvalue = config;
hpriv->config_index = config - 1;
@@ -1122,9 +1122,6 @@ int
sunos_claim_interface(struct libusb_device_handle *handle, int iface)
{
usbi_dbg("iface %d", iface);
- if (iface < 0) {
- return (LIBUSB_ERROR_INVALID_PARAM);
- }
return (LIBUSB_SUCCESS);
}
@@ -1135,9 +1132,6 @@ sunos_release_interface(struct libusb_device_handle *handle, int iface)
sunos_dev_handle_priv_t *hpriv = usbi_get_device_handle_priv(handle);
usbi_dbg("iface %d", iface);
- if (iface < 0) {
- return (LIBUSB_ERROR_INVALID_PARAM);
- }
/* XXX: can we release it? */
hpriv->altsetting[iface] = 0;
@@ -1154,9 +1148,6 @@ sunos_set_interface_altsetting(struct libusb_device_handle *handle, int iface,
usbi_dbg("iface %d, setting %d", iface, altsetting);
- if (iface < 0 || altsetting < 0) {
- return (LIBUSB_ERROR_INVALID_PARAM);
- }
if (dpriv->ugenpath == NULL)
return (LIBUSB_ERROR_NOT_FOUND);
diff --git a/libusb/os/windows_usbdk.c b/libusb/os/windows_usbdk.c
index 9c3e8fd..bb370ca 100644
--- a/libusb/os/windows_usbdk.c
+++ b/libusb/os/windows_usbdk.c
@@ -286,7 +286,6 @@ static void usbdk_device_init(libusb_device *dev, PUSB_DK_DEVICE_INFO info)
// Addresses in libusb are 1-based
dev->device_address = (uint8_t)(info->Port + 1);
- dev->num_configurations = info->DeviceDescriptor.bNumConfigurations;
memcpy(&dev->device_descriptor, &info->DeviceDescriptor, LIBUSB_DT_DEVICE_SIZE);
switch (info->Speed) {
@@ -373,9 +372,6 @@ static int usbdk_get_config_descriptor(struct libusb_device *dev, uint8_t config
PUSB_CONFIGURATION_DESCRIPTOR config_header;
size_t size;
- if (config_index >= dev->num_configurations)
- return LIBUSB_ERROR_INVALID_PARAM;
-
config_header = (PUSB_CONFIGURATION_DESCRIPTOR)priv->config_descriptors[config_index];
size = min(config_header->wTotalLength, len);
@@ -390,7 +386,7 @@ static int usbdk_get_config_descriptor_by_value(struct libusb_device *dev, uint8
PUSB_CONFIGURATION_DESCRIPTOR config_header;
uint8_t index;
- for (index = 0; index < dev->num_configurations; index++) {
+ for (index = 0; index < dev->device_descriptor.bNumConfigurations; index++) {
config_header = priv->config_descriptors[index];
if (config_header->bConfigurationValue == bConfigurationValue) {
*buffer = (unsigned char *)priv->config_descriptors[index];
diff --git a/libusb/os/windows_winusb.c b/libusb/os/windows_winusb.c
index ef6fbd2..245df90 100644
--- a/libusb/os/windows_winusb.c
+++ b/libusb/os/windows_winusb.c
@@ -681,27 +681,28 @@ static void cache_config_descriptors(struct libusb_device *dev, HANDLE hub_handl
struct libusb_context *ctx = DEVICE_CTX(dev);
struct winusb_device_priv *priv = usbi_get_device_priv(dev);
DWORD size, ret_size;
- uint8_t i;
+ uint8_t i, num_configurations;
USB_CONFIGURATION_DESCRIPTOR_SHORT cd_buf_short; // dummy request
PUSB_DESCRIPTOR_REQUEST cd_buf_actual = NULL; // actual request
PUSB_CONFIGURATION_DESCRIPTOR cd_data;
- if (dev->num_configurations == 0)
+ num_configurations = priv->dev_descriptor.bNumConfigurations;
+ if (num_configurations == 0)
return;
assert(sizeof(USB_DESCRIPTOR_REQUEST) == USB_DESCRIPTOR_REQUEST_SIZE);
- priv->config_descriptor = calloc(dev->num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
+ priv->config_descriptor = calloc(num_configurations, sizeof(PUSB_CONFIGURATION_DESCRIPTOR));
if (priv->config_descriptor == NULL) {
usbi_err(ctx, "could not allocate configuration descriptor array for '%s'", priv->dev_id);
return;
}
- for (i = 0; i <= dev->num_configurations; i++) {
+ for (i = 0; i <= num_configurations; i++) {
safe_free(cd_buf_actual);
- if (i == dev->num_configurations)
+ if (i == num_configurations)
break;
size = sizeof(cd_buf_short);
@@ -860,13 +861,12 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
}
memcpy(&priv->dev_descriptor, &(conn_info.DeviceDescriptor), sizeof(USB_DEVICE_DESCRIPTOR));
- dev->num_configurations = conn_info.DeviceDescriptor.bNumConfigurations;
priv->active_config = conn_info.CurrentConfigurationValue;
if (priv->active_config == 0) {
usbi_dbg("0x%x:0x%x found %u configurations (not configured)",
priv->dev_descriptor.idVendor,
priv->dev_descriptor.idProduct,
- dev->num_configurations);
+ priv->dev_descriptor.bNumConfigurations);
SleepEx(50, TRUE);
}
} while (priv->active_config == 0 && --ginfotimeout >= 0);
@@ -876,10 +876,10 @@ static int init_device(struct libusb_device *dev, struct libusb_device *parent_d
"forcing current configuration to 1",
priv->dev_descriptor.idVendor,
priv->dev_descriptor.idProduct,
- dev->num_configurations);
+ priv->dev_descriptor.bNumConfigurations);
priv->active_config = 1;
} else {
- usbi_dbg("found %u configurations (current config: %u)", dev->num_configurations, priv->active_config);
+ usbi_dbg("found %u configurations (current config: %u)", priv->dev_descriptor.bNumConfigurations, priv->active_config);
}
// Cache as many config descriptors as we can
@@ -957,7 +957,6 @@ static int enumerate_hcd_root_hub(struct libusb_context *ctx, const char *dev_id
usbi_dbg("assigning HCD '%s' bus number %u", dev_id, bus_number);
priv = usbi_get_device_priv(dev);
dev->bus_number = bus_number;
- dev->num_configurations = 1;
priv->dev_descriptor.bLength = LIBUSB_DT_DEVICE_SIZE;
priv->dev_descriptor.bDescriptorType = LIBUSB_DT_DEVICE;
priv->dev_descriptor.bDeviceClass = LIBUSB_CLASS_HUB;
@@ -1543,10 +1542,6 @@ static int winusb_get_config_descriptor(struct libusb_device *dev, uint8_t confi
PUSB_CONFIGURATION_DESCRIPTOR config_header;
size_t size;
- // config index is zero based
- if (config_index >= dev->num_configurations)
- return LIBUSB_ERROR_INVALID_PARAM;
-
if ((priv->config_descriptor == NULL) || (priv->config_descriptor[config_index] == NULL))
return LIBUSB_ERROR_NOT_FOUND;
@@ -1567,7 +1562,7 @@ static int winusb_get_config_descriptor_by_value(struct libusb_device *dev, uint
if (priv->config_descriptor == NULL)
return LIBUSB_ERROR_NOT_FOUND;
- for (index = 0; index < dev->num_configurations; index++) {
+ for (index = 0; index < dev->device_descriptor.bNumConfigurations; index++) {
config_header = priv->config_descriptor[index];
if (config_header == NULL)
continue;
@@ -1641,9 +1636,6 @@ static int winusb_set_configuration(struct libusb_device_handle *dev_handle, int
struct winusb_device_priv *priv = usbi_get_device_priv(dev_handle->dev);
int r = LIBUSB_SUCCESS;
- if (config >= USB_MAXCONFIG)
- return LIBUSB_ERROR_INVALID_PARAM;
-
r = libusb_control_transfer(dev_handle, LIBUSB_ENDPOINT_OUT |
LIBUSB_REQUEST_TYPE_STANDARD | LIBUSB_RECIPIENT_DEVICE,
LIBUSB_REQUEST_SET_CONFIGURATION, (uint16_t)config,
@@ -2478,9 +2470,6 @@ static int winusbx_set_interface_altsetting(int sub_api, struct libusb_device_ha
CHECK_WINUSBX_AVAILABLE(sub_api);
- if (altsetting > 255)
- return LIBUSB_ERROR_INVALID_PARAM;
-
winusb_handle = handle_priv->interface_handle[iface].api_handle;
if (!HANDLE_VALID(winusb_handle)) {
usbi_err(HANDLE_CTX(dev_handle), "interface must be claimed first");
@@ -3592,9 +3581,6 @@ static int hid_set_interface_altsetting(int sub_api, struct libusb_device_handle
CHECK_HID_AVAILABLE;
- if (altsetting > 255)
- return LIBUSB_ERROR_INVALID_PARAM;
-
if (altsetting != 0) {
usbi_err(HANDLE_CTX(dev_handle), "set interface altsetting not supported for altsetting >0");
return LIBUSB_ERROR_NOT_SUPPORTED;
@@ -3615,7 +3601,7 @@ static int hid_submit_control_transfer(int sub_api, struct usbi_transfer *itrans
OVERLAPPED *overlapped;
int current_interface, config;
size_t size;
- int r = LIBUSB_ERROR_INVALID_PARAM;
+ int r;
UNUSED(sub_api);
CHECK_HID_AVAILABLE;
diff --git a/libusb/os/windows_winusb.h b/libusb/os/windows_winusb.h
index c8d3f15..0340fe7 100644
--- a/libusb/os/windows_winusb.h
+++ b/libusb/os/windows_winusb.h
@@ -220,8 +220,8 @@ static inline void winusb_device_priv_release(struct libusb_device *dev)
free(priv->dev_id);
free(priv->path);
- if ((dev->num_configurations > 0) && (priv->config_descriptor != NULL)) {
- for (i = 0; i < dev->num_configurations; i++) {
+ if ((priv->dev_descriptor.bNumConfigurations > 0) && (priv->config_descriptor != NULL)) {
+ for (i = 0; i < priv->dev_descriptor.bNumConfigurations; i++) {
if (priv->config_descriptor[i] == NULL)
continue;
free((UCHAR *)priv->config_descriptor[i] - USB_DESCRIPTOR_REQUEST_SIZE);
diff --git a/libusb/version_nano.h b/libusb/version_nano.h
index 3804599..a744f2f 100644
--- a/libusb/version_nano.h
+++ b/libusb/version_nano.h
@@ -1 +1 @@
-#define LIBUSB_NANO 11464
+#define LIBUSB_NANO 11465