summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--class/adb/usbd_adb_sync.c23
-rw-r--r--class/audio/usbh_audio.c9
-rw-r--r--class/cdc/usbh_cdc_ncm.c33
-rw-r--r--class/msc/usbd_msc.c37
-rw-r--r--class/tmc/usbd_tmc.c22
-rw-r--r--class/vendor/net/usbh_asix.c10
-rw-r--r--class/vendor/net/usbh_rtl8152.c15
-rw-r--r--class/video/usbh_video.c42
-rw-r--r--class/wireless/usbd_rndis.c13
-rw-r--r--class/wireless/usbh_rndis.c10
-rw-r--r--common/usb_def.h1
-rw-r--r--common/usb_log.h17
-rw-r--r--core/usbd_core.c57
-rw-r--r--core/usbh_core.c133
-rw-r--r--demo/adb_template.c1
-rw-r--r--demo/gs_usb_template.c1
-rw-r--r--demo/mtp_template.c1
-rw-r--r--demo/winusb1.0_template.c1
-rw-r--r--tools/test_srcipts/libusb_winusb_device_for_speed.c1
19 files changed, 330 insertions, 97 deletions
diff --git a/class/adb/usbd_adb_sync.c b/class/adb/usbd_adb_sync.c
index b18e2b09..9ab0a95b 100644
--- a/class/adb/usbd_adb_sync.c
+++ b/class/adb/usbd_adb_sync.c
@@ -234,36 +234,28 @@ static bool adb_sync_name_is_dir(const char *path)
* "/sdc/.\output/...". FatFs takes both separators alike, so the backslashes
* are folded into forward ones before any component is looked at - otherwise
* ".\output" stays a single, unmakable name and the push dies on the first
- * file. The checks above run first, so this never turns a relative path into
- * something that looks absolute. */
-static bool adb_sync_build_full_path(const char *root, char *path, bool *wants_dir)
+ * file. After folding separators, the path must start with '/'. */
+static bool adb_sync_build_full_path(char *path, bool *wants_dir)
{
char *dst0;
char *dst;
char *src;
size_t len;
- size_t root_len;
size_t i;
*wants_dir = false;
- root_len = strlen(root);
len = strlen(path);
- if ((root_len == 0u) || (len < root_len) || (strncmp(path, root, root_len) != 0)) {
- return false;
- }
-
- if ((len > root_len) && (root[root_len - 1u] != '/') && (path[root_len] != '/')) {
- return false;
- }
-
for (i = 0u; i < len; i++) {
if (path[i] == '\\') {
path[i] = '/';
}
}
+ if (path[0] != '/') {
+ return false;
+ }
*wants_dir = (len > 1u) && (path[len - 1u] == '/');
dst0 = path;
@@ -754,9 +746,8 @@ static void adb_sync_dispatch(uint32_t id, char *body)
len = strlen(body);
memcpy(g_adb_sync.path, body, len + 1u);
- if (adb_sync_build_full_path(vfs_get_fs_root_path(), g_adb_sync.path, &wants_dir) == false) {
- adb_sync_fail("the path has to be absolute, starting with '%s', not '%s'",
- vfs_get_fs_root_path(), g_adb_sync.path);
+ if (adb_sync_build_full_path(g_adb_sync.path, &wants_dir) == false) {
+ adb_sync_fail("the path has to be absolute, starting with '/', not '%s'", g_adb_sync.path);
return;
}
diff --git a/class/audio/usbh_audio.c b/class/audio/usbh_audio.c
index 5ef08c90..3fcae863 100644
--- a/class/audio/usbh_audio.c
+++ b/class/audio/usbh_audio.c
@@ -672,6 +672,9 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
case USB_DESCRIPTOR_TYPE_ENDPOINT:
if (cur_iface == audio_class->ctrl_intf) {
} else if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
+ if (cur_iface - audio_class->ctrl_intf - 1 >= CONFIG_USBHOST_AUDIO_MAX_STREAMS) {
+ return -USB_ERR_INVAL;
+ }
struct usb_endpoint_descriptor *ep_desc = (struct usb_endpoint_descriptor *)p;
if (ep_desc->bEndpointAddress & 0x80) {
audio_class->as_msg_table[cur_iface - audio_class->ctrl_intf - 1].is_tx = false;
@@ -702,6 +705,9 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
break;
}
} else if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
+ if (cur_iface - audio_class->ctrl_intf - 1 >= CONFIG_USBHOST_AUDIO_MAX_STREAMS) {
+ return -USB_ERR_INVAL;
+ }
switch (p[DESC_bDescriptorSubType]) {
case AUDIO_STREAMING_GENERAL: {
struct audio_cs_if_as_general_descriptor *desc = (struct audio_cs_if_as_general_descriptor *)p;
@@ -727,6 +733,9 @@ static int usbh_audio_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
break;
case AUDIO_ENDPOINT_DESCRIPTOR_TYPE:
if ((cur_iface > audio_class->ctrl_intf) && (cur_iface < (audio_class->ctrl_intf + cur_iface_count))) {
+ if (cur_iface - audio_class->ctrl_intf - 1 >= CONFIG_USBHOST_AUDIO_MAX_STREAMS) {
+ return -USB_ERR_INVAL;
+ }
if (p[DESC_bDescriptorSubType] == AUDIO_ENDPOINT_GENERAL) {
struct audio_cs_ep_ep_general_descriptor *desc = (struct audio_cs_ep_ep_general_descriptor *)p;
diff --git a/class/cdc/usbh_cdc_ncm.c b/class/cdc/usbh_cdc_ncm.c
index 83310e09..04e330b8 100644
--- a/class/cdc/usbh_cdc_ncm.c
+++ b/class/cdc/usbh_cdc_ncm.c
@@ -296,6 +296,9 @@ void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
if (g_cdc_ncm_rx_length < CONFIG_USBHOST_CDC_NCM_ETH_MAX_RX_SIZE) {
USB_LOG_DBG("rxlen:%d\r\n", g_cdc_ncm_rx_length);
+ if (g_cdc_ncm_rx_length < sizeof(struct cdc_ncm_nth16)) {
+ continue;
+ }
struct cdc_ncm_nth16 *nth16 = (struct cdc_ncm_nth16 *)&g_cdc_ncm_rx_buffer[0];
if ((nth16->dwSignature != CDC_NCM_NTH16_SIGNATURE) ||
(nth16->wHeaderLength != 12) ||
@@ -305,6 +308,12 @@ void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
continue;
}
+ if (nth16->wNdpIndex < sizeof(struct cdc_ncm_nth16) ||
+ (nth16->wNdpIndex & 3) ||
+ nth16->wNdpIndex > g_cdc_ncm_rx_length - sizeof(struct cdc_ncm_ndp16)) {
+ USB_LOG_ERR("invalid rx ndp16 index\r\n");
+ continue;
+ }
struct cdc_ncm_ndp16 *ndp16 = (struct cdc_ncm_ndp16 *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex];
if ((ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM0) && (ndp16->dwSignature != CDC_NCM_NDP16_SIGNATURE_NCM1)) {
USB_LOG_ERR("invalid rx ndp16\r\n");
@@ -312,17 +321,31 @@ void usbh_cdc_ncm_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
continue;
}
+ if (ndp16->wLength < sizeof(struct cdc_ncm_ndp16) + sizeof(struct cdc_ncm_ndp16_datagram) ||
+ (ndp16->wLength & 3) ||
+ ndp16->wLength > g_cdc_ncm_rx_length - nth16->wNdpIndex) {
+ USB_LOG_ERR("invalid rx ndp16 length\r\n");
+ continue;
+ }
uint16_t datagram_num = (ndp16->wLength - 8) / 4;
USB_LOG_DBG("datagram num:%02x\r\n", datagram_num);
for (uint16_t i = 0; i < datagram_num; i++) {
struct cdc_ncm_ndp16_datagram *ndp16_datagram = (struct cdc_ncm_ndp16_datagram *)&g_cdc_ncm_rx_buffer[nth16->wNdpIndex + 8 + 4 * i];
- if (ndp16_datagram->wDatagramIndex && ndp16_datagram->wDatagramLength) {
- USB_LOG_DBG("ndp16_datagram index:%02x, length:%02x\r\n", ndp16_datagram->wDatagramIndex, ndp16_datagram->wDatagramLength);
-
- uint8_t *buf = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex];
- usbh_cdc_ncm_eth_input(buf, ndp16_datagram->wDatagramLength);
+ if (!ndp16_datagram->wDatagramIndex && !ndp16_datagram->wDatagramLength) {
+ break;
}
+ if (ndp16_datagram->wDatagramIndex < sizeof(struct cdc_ncm_nth16) ||
+ ndp16_datagram->wDatagramIndex > g_cdc_ncm_rx_length ||
+ !ndp16_datagram->wDatagramLength ||
+ ndp16_datagram->wDatagramLength > g_cdc_ncm_rx_length - ndp16_datagram->wDatagramIndex) {
+ USB_LOG_ERR("invalid rx datagram range\r\n");
+ break;
+ }
+ USB_LOG_DBG("ndp16_datagram index:%02x, length:%02x\r\n", ndp16_datagram->wDatagramIndex, ndp16_datagram->wDatagramLength);
+
+ uint8_t *buf = (uint8_t *)&g_cdc_ncm_rx_buffer[ndp16_datagram->wDatagramIndex];
+ usbh_cdc_ncm_eth_input(buf, ndp16_datagram->wDatagramLength);
}
g_cdc_ncm_rx_length = 0;
diff --git a/class/msc/usbd_msc.c b/class/msc/usbd_msc.c
index d21051f0..cd3fc4f7 100644
--- a/class/msc/usbd_msc.c
+++ b/class/msc/usbd_msc.c
@@ -538,6 +538,26 @@ static bool SCSI_readCapacity16(uint8_t busid, uint8_t **data, uint32_t *len)
return true;
}
+/* Check the range before adding LBAs or multiplying the transfer size. */
+static bool SCSI_checkReadWriteRange(uint8_t busid)
+{
+ uint8_t lun = g_usbd_msc[busid].cbw.bLUN;
+ uint32_t capacity = g_usbd_msc[busid].scsi_blk_nbr[lun];
+ uint32_t block_size = g_usbd_msc[busid].scsi_blk_size[lun];
+
+ if (g_usbd_msc[busid].start_sector >= capacity ||
+ g_usbd_msc[busid].nsectors > capacity - g_usbd_msc[busid].start_sector) {
+ SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE);
+ return false;
+ }
+ if (block_size == 0 || g_usbd_msc[busid].nsectors == 0 ||
+ g_usbd_msc[busid].nsectors > UINT32_MAX / block_size) {
+ SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDFIELDINCBA);
+ return false;
+ }
+ return true;
+}
+
static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
{
(void)data;
@@ -551,8 +571,7 @@ static bool SCSI_read10(uint8_t busid, uint8_t **data, uint32_t *len)
g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
g_usbd_msc[busid].nsectors = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]); /* Number of Blocks to transfer */
- if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
- SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE);
+ if (!SCSI_checkReadWriteRange(busid)) {
return false;
}
@@ -584,8 +603,7 @@ static bool SCSI_read12(uint8_t busid, uint8_t **data, uint32_t *len)
g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
g_usbd_msc[busid].nsectors = GET_BE32(&g_usbd_msc[busid].cbw.CB[6]); /* Number of Blocks to transfer */
- if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
- SCSI_SetSenseData(busid, SCSI_KCQIR_LBAOUTOFRANGE);
+ if (!SCSI_checkReadWriteRange(busid)) {
return false;
}
@@ -619,10 +637,10 @@ static bool SCSI_write10(uint8_t busid, uint8_t **data, uint32_t *len)
g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
g_usbd_msc[busid].nsectors = GET_BE16(&g_usbd_msc[busid].cbw.CB[7]); /* Number of Blocks to transfer */
- data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN];
- if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
+ if (!SCSI_checkReadWriteRange(busid)) {
return false;
}
+ data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN];
if (g_usbd_msc[busid].cbw.dDataLength != data_len) {
return false;
@@ -648,10 +666,10 @@ static bool SCSI_write12(uint8_t busid, uint8_t **data, uint32_t *len)
g_usbd_msc[busid].start_sector = GET_BE32(&g_usbd_msc[busid].cbw.CB[2]); /* Logical Block Address of First Block */
g_usbd_msc[busid].nsectors = GET_BE32(&g_usbd_msc[busid].cbw.CB[6]); /* Number of Blocks to transfer */
- data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN];
- if ((g_usbd_msc[busid].start_sector + g_usbd_msc[busid].nsectors) > g_usbd_msc[busid].scsi_blk_nbr[g_usbd_msc[busid].cbw.bLUN]) {
+ if (!SCSI_checkReadWriteRange(busid)) {
return false;
}
+ data_len = g_usbd_msc[busid].nsectors * g_usbd_msc[busid].scsi_blk_size[g_usbd_msc[busid].cbw.bLUN];
if (g_usbd_msc[busid].cbw.dDataLength != data_len) {
return false;
@@ -736,6 +754,9 @@ static bool SCSI_CBWDecode(uint8_t busid, uint32_t nbytes)
if ((g_usbd_msc[busid].cbw.dSignature != MSC_CBW_Signature) || (g_usbd_msc[busid].cbw.bCBLength < 1) || (g_usbd_msc[busid].cbw.bCBLength > 16)) {
SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDCOMMAND);
return false;
+ } else if (g_usbd_msc[busid].cbw.bLUN > g_usbd_msc[busid].max_lun) {
+ SCSI_SetSenseData(busid, SCSI_KCQIR_INVALIDLUN);
+ return false;
} else {
USB_LOG_DBG("Decode CB:0x%02x\r\n", g_usbd_msc[busid].cbw.CB[0]);
switch (g_usbd_msc[busid].cbw.CB[0]) {
diff --git a/class/tmc/usbd_tmc.c b/class/tmc/usbd_tmc.c
index 7f351e99..e3d9a0fc 100644
--- a/class/tmc/usbd_tmc.c
+++ b/class/tmc/usbd_tmc.c
@@ -166,13 +166,23 @@ void tmc_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
struct tmc_bulk_header *out_header = (struct tmc_bulk_header *)tmc_read_buffer;
struct tmc_bulk_header *in_header = (struct tmc_bulk_header *)tmc_write_buffer;
+ if (g_tmc_read_offset > sizeof(tmc_read_buffer) ||
+ nbytes > sizeof(tmc_read_buffer) - g_tmc_read_offset) {
+ goto reset_read;
+ }
g_tmc_read_offset += nbytes;
if (g_tmc_read_total == 0) {
- USB_ASSERT_MSG(nbytes >= sizeof(struct tmc_bulk_header), "tmc header size error\r\n");
+ if (nbytes < sizeof(struct tmc_bulk_header)) {
+ goto reset_read;
+ }
switch (out_header->MsgID) {
case TMC_MSGID_OUT_DEV_DEP_MSG_OUT:
+ if (out_header->msg_specific.dev_dep_msg_out.transferSize >
+ ((sizeof(tmc_read_buffer) - sizeof(struct tmc_bulk_header)) & ~3u)) {
+ goto reset_read;
+ }
g_tmc_read_total = ((out_header->msg_specific.dev_dep_msg_out.transferSize + 3u) & ~3u) + sizeof(struct tmc_bulk_header);
break;
case TMC_MSGID_OUT_REQUEST_DEV_DEP_MSG_IN:
@@ -182,9 +192,14 @@ void tmc_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
USB_LOG_WRN("Unhandled TMC MsgID 0x%02x\r\n", out_header->MsgID);
break;
}
- USB_ASSERT_MSG(g_tmc_read_total <= CONFIG_USBDEV_TMC_MAX_BUFSIZE, "tmc read buffer overflow\r\n");
+ if (g_tmc_read_total == 0 || g_tmc_read_total > sizeof(tmc_read_buffer)) {
+ goto reset_read;
+ }
}
+ if (g_tmc_read_offset > g_tmc_read_total) {
+ goto reset_read;
+ }
if (g_tmc_read_offset < g_tmc_read_total) {
usbd_ep_start_read(busid, tmc_ep_data[TMC_OUT_EP_IDX].ep_addr, tmc_read_buffer + g_tmc_read_offset, usbd_get_ep_mps(busid, tmc_ep_data[TMC_OUT_EP_IDX].ep_addr));
return;
@@ -194,7 +209,7 @@ void tmc_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
case TMC_MSGID_OUT_DEV_DEP_MSG_OUT:
SCPI_Input(&scpi_context,
(const char *)(tmc_read_buffer + sizeof(struct tmc_bulk_header)),
- g_tmc_read_total);
+ out_header->msg_specific.dev_dep_msg_out.transferSize);
break;
case TMC_MSGID_OUT_REQUEST_DEV_DEP_MSG_IN:
@@ -211,6 +226,7 @@ void tmc_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
break;
}
+reset_read:
g_tmc_read_offset = 0;
g_tmc_read_total = 0;
usbd_ep_start_read(busid, tmc_ep_data[TMC_OUT_EP_IDX].ep_addr, tmc_read_buffer + g_tmc_read_offset, usbd_get_ep_mps(busid, tmc_ep_data[TMC_OUT_EP_IDX].ep_addr));
diff --git a/class/vendor/net/usbh_asix.c b/class/vendor/net/usbh_asix.c
index e63b274b..706b5c9c 100644
--- a/class/vendor/net/usbh_asix.c
+++ b/class/vendor/net/usbh_asix.c
@@ -718,10 +718,13 @@ void usbh_asix_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
data_offset = 0;
while (g_asix_rx_length > 0) {
+ if (g_asix_rx_length < 4) {
+ break;
+ }
len = ((uint16_t)g_asix_rx_buffer[data_offset + 0] | ((uint16_t)(g_asix_rx_buffer[data_offset + 1]) << 8)) & 0x7ff;
len_crc = g_asix_rx_buffer[data_offset + 2] | ((uint16_t)(g_asix_rx_buffer[data_offset + 3]) << 8);
- if (len != (~len_crc & 0x7ff)) {
+ if (len != (~len_crc & 0x7ff) || len == 0 || (len > g_asix_rx_length - 4)) {
USB_LOG_ERR("rx header error\r\n");
g_asix_rx_length = 0;
continue;
@@ -732,8 +735,9 @@ void usbh_asix_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
g_asix_rx_length -= (len + 4);
data_offset += (len + 4);
- if (g_asix_rx_length < 4) {
- g_asix_rx_length = 0;
+ if ((len & 1) && g_asix_rx_length > 0) {
+ g_asix_rx_length--;
+ data_offset++;
}
}
} else {
diff --git a/class/vendor/net/usbh_rtl8152.c b/class/vendor/net/usbh_rtl8152.c
index 16393ab1..df5f3d3b 100644
--- a/class/vendor/net/usbh_rtl8152.c
+++ b/class/vendor/net/usbh_rtl8152.c
@@ -2186,9 +2186,16 @@ void usbh_rtl8152_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
USB_LOG_DBG("rxlen:%d\r\n", g_rtl8152_rx_length);
while (g_rtl8152_rx_length > 0) {
+ if (g_rtl8152_rx_length < sizeof(struct rx_desc)) {
+ break;
+ }
struct rx_desc *rx_desc = (struct rx_desc *)&g_rtl8152_rx_buffer[data_offset];
len = rx_desc->opts1 & RX_LEN_MASK;
+ if (len == 0 || len > g_rtl8152_rx_length - sizeof(struct rx_desc)) {
+ USB_LOG_ERR("invalid rtl8152 rx length\r\n");
+ break;
+ }
USB_LOG_DBG("data_offset:%d, eth len:%d\r\n", data_offset, len);
@@ -2199,8 +2206,12 @@ void usbh_rtl8152_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
g_rtl8152_rx_length -= (len + sizeof(struct rx_desc));
if (len & (RX_ALIGN - 1)) {
- data_offset += (RX_ALIGN - (len & (RX_ALIGN - 1)));
- g_rtl8152_rx_length -= (RX_ALIGN - (len & (RX_ALIGN - 1)));
+ uint32_t padding = RX_ALIGN - (len & (RX_ALIGN - 1));
+ if (padding > g_rtl8152_rx_length) {
+ break;
+ }
+ data_offset += padding;
+ g_rtl8152_rx_length -= padding;
}
}
} else {
diff --git a/class/video/usbh_video.c b/class/video/usbh_video.c
index 8e782e20..2c479740 100644
--- a/class/video/usbh_video.c
+++ b/class/video/usbh_video.c
@@ -367,7 +367,8 @@ void usbh_video_list_info(struct usbh_video *video_class)
USB_LOG_RAW(" wWidth: %d, wHeight: %d, fps: %d\r\n",
video_class->format[i].frame[j].wWidth,
video_class->format[i].frame[j].wHeight,
- (1000 / (video_class->format[i].frame[j].dwDefaultFrameInterval / 10000)));
+ (video_class->format[i].frame[j].dwDefaultFrameInterval ?
+ 10000000U / video_class->format[i].frame[j].dwDefaultFrameInterval : 0U));
}
}
@@ -418,6 +419,9 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
if (cur_iface == video_class->ctrl_intf) {
switch (p[DESC_bDescriptorSubType]) {
case VIDEO_VC_HEADER_DESCRIPTOR_SUBTYPE:
+ if (p[DESC_bLength] < 5) {
+ return -USB_ERR_INVAL;
+ }
video_class->bcdVDC = ((uint16_t)p[4] << 8) | (uint16_t)p[3];
break;
case VIDEO_VC_INPUT_TERMINAL_DESCRIPTOR_SUBTYPE:
@@ -433,11 +437,22 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
} else if (cur_iface == video_class->data_intf) {
switch (p[DESC_bDescriptorSubType]) {
case VIDEO_VS_INPUT_HEADER_DESCRIPTOR_SUBTYPE:
+ if (p[DESC_bLength] < 4 || p[DESC_bNumFormats] == 0 ||
+ p[DESC_bNumFormats] > CONFIG_USBHOST_VIDEO_MAX_FORMATS) {
+ return -USB_ERR_INVAL;
+ }
video_class->num_of_formats = p[DESC_bNumFormats];
break;
case VIDEO_VS_FORMAT_UNCOMPRESSED_DESCRIPTOR_SUBTYPE:
+ if (p[DESC_bLength] < 5) {
+ return -USB_ERR_INVAL;
+ }
format_index = p[DESC_bFormatIndex];
num_of_frames = p[DESC_bNumFrameDescriptors];
+ if (format_index == 0 || format_index > CONFIG_USBHOST_VIDEO_MAX_FORMATS ||
+ num_of_frames == 0 || num_of_frames > CONFIG_USBHOST_VIDEO_MAX_FRAMES) {
+ return -USB_ERR_INVAL;
+ }
USB_ASSERT(format_index != 0);
USB_ASSERT(format_index <= CONFIG_USBHOST_VIDEO_MAX_FORMATS);
@@ -446,8 +461,15 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
video_class->format[format_index - 1].format_type = USBH_VIDEO_FORMAT_UNCOMPRESSED;
break;
case VIDEO_VS_FORMAT_MJPEG_DESCRIPTOR_SUBTYPE:
+ if (p[DESC_bLength] < 5) {
+ return -USB_ERR_INVAL;
+ }
format_index = p[DESC_bFormatIndex];
num_of_frames = p[DESC_bNumFrameDescriptors];
+ if (format_index == 0 || format_index > CONFIG_USBHOST_VIDEO_MAX_FORMATS ||
+ num_of_frames == 0 || num_of_frames > CONFIG_USBHOST_VIDEO_MAX_FRAMES) {
+ return -USB_ERR_INVAL;
+ }
USB_ASSERT(format_index != 0);
USB_ASSERT(format_index <= CONFIG_USBHOST_VIDEO_MAX_FORMATS);
@@ -456,7 +478,16 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
video_class->format[format_index - 1].format_type = USBH_VIDEO_FORMAT_MJPEG;
break;
case VIDEO_VS_FRAME_UNCOMPRESSED_DESCRIPTOR_SUBTYPE:
+ if (p[DESC_bLength] < sizeof(struct video_cs_if_vs_frame_uncompressed_descriptor)) {
+ return -USB_ERR_INVAL;
+ }
frame_index = p[DESC_bFrameIndex];
+ if (format_index == 0 || format_index > CONFIG_USBHOST_VIDEO_MAX_FORMATS ||
+ frame_index == 0 || frame_index > CONFIG_USBHOST_VIDEO_MAX_FRAMES ||
+ frame_index > video_class->format[format_index - 1].num_of_frames ||
+ ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->dwDefaultFrameInterval == 0) {
+ return -USB_ERR_INVAL;
+ }
USB_ASSERT(format_index != 0);
USB_ASSERT(frame_index != 0);
@@ -468,7 +499,16 @@ static int usbh_video_ctrl_connect(struct usbh_hubport *hport, uint8_t intf)
video_class->format[format_index - 1].frame[frame_index - 1].dwDefaultFrameInterval = ((struct video_cs_if_vs_frame_uncompressed_descriptor *)p)->dwDefaultFrameInterval;
break;
case VIDEO_VS_FRAME_MJPEG_DESCRIPTOR_SUBTYPE:
+ if (p[DESC_bLength] < sizeof(struct video_cs_if_vs_frame_mjpeg_descriptor)) {
+ return -USB_ERR_INVAL;
+ }
frame_index = p[DESC_bFrameIndex];
+ if (format_index == 0 || format_index > CONFIG_USBHOST_VIDEO_MAX_FORMATS ||
+ frame_index == 0 || frame_index > CONFIG_USBHOST_VIDEO_MAX_FRAMES ||
+ frame_index > video_class->format[format_index - 1].num_of_frames ||
+ ((struct video_cs_if_vs_frame_mjpeg_descriptor *)p)->dwDefaultFrameInterval == 0) {
+ return -USB_ERR_INVAL;
+ }
USB_ASSERT(format_index != 0);
USB_ASSERT(frame_index != 0);
diff --git a/class/wireless/usbd_rndis.c b/class/wireless/usbd_rndis.c
index ea62c50e..08366250 100644
--- a/class/wireless/usbd_rndis.c
+++ b/class/wireless/usbd_rndis.c
@@ -477,8 +477,18 @@ void rndis_bulk_out(uint8_t busid, uint8_t ep, uint32_t nbytes)
(void)busid;
(void)ep;
+ if (nbytes < sizeof(rndis_data_packet_t)) {
+ usbd_rndis_start_read((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_total_length);
+ return;
+ }
+
hdr = (rndis_data_packet_t *)g_rndis_rx_data_buffer;
- if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) || (nbytes < hdr->MessageLength)) {
+ if ((hdr->MessageType != REMOTE_NDIS_PACKET_MSG) ||
+ (hdr->MessageLength < sizeof(rndis_data_packet_t)) ||
+ (hdr->MessageLength > nbytes) ||
+ (hdr->DataOffset < sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t)) ||
+ (hdr->DataOffset > hdr->MessageLength - sizeof(rndis_generic_msg_t)) ||
+ (hdr->DataLength > hdr->MessageLength - sizeof(rndis_generic_msg_t) - hdr->DataOffset)) {
usbd_rndis_start_read((uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_total_length);
return;
}
@@ -555,6 +565,7 @@ struct pbuf *usbd_rndis_eth_rx(void)
usbd_rndis_start_read(g_rndis_rx_buffer, sizeof(g_rndis_rx_buffer));
return NULL;
}
+
usb_memcpy(p->payload, (uint8_t *)g_rndis_rx_data_buffer, g_rndis_rx_data_length);
p->len = g_rndis_rx_data_length;
diff --git a/class/wireless/usbh_rndis.c b/class/wireless/usbh_rndis.c
index 22f0e369..d6354d5a 100644
--- a/class/wireless/usbh_rndis.c
+++ b/class/wireless/usbh_rndis.c
@@ -544,6 +544,9 @@ void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
while (g_rndis_rx_length > 0) {
USB_LOG_DBG("rxlen:%u\r\n", (unsigned int)g_rndis_rx_length);
+ if (g_rndis_rx_length < sizeof(rndis_data_packet_t)) {
+ break;
+ }
pmsg = (rndis_data_packet_t *)(g_rndis_rx_buffer + pmg_offset);
/* Not word-aligned case */
@@ -552,7 +555,12 @@ void usbh_rndis_rx_thread(CONFIG_USB_OSAL_THREAD_SET_ARGV)
pmsg = &temp;
}
- if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG) {
+ if (pmsg->MessageType == REMOTE_NDIS_PACKET_MSG &&
+ pmsg->MessageLength >= sizeof(rndis_data_packet_t) &&
+ pmsg->MessageLength <= g_rndis_rx_length &&
+ pmsg->DataOffset >= sizeof(rndis_data_packet_t) - sizeof(rndis_generic_msg_t) &&
+ pmsg->DataOffset <= pmsg->MessageLength - sizeof(rndis_generic_msg_t) &&
+ pmsg->DataLength <= pmsg->MessageLength - sizeof(rndis_generic_msg_t) - pmsg->DataOffset) {
uint8_t *buf = (uint8_t *)(g_rndis_rx_buffer + pmg_offset + sizeof(rndis_generic_msg_t) + pmsg->DataOffset);
usbh_rndis_eth_input(buf, pmsg->DataLength);
diff --git a/common/usb_def.h b/common/usb_def.h
index 73d2b800..cf0cb089 100644
--- a/common/usb_def.h
+++ b/common/usb_def.h
@@ -513,6 +513,7 @@ struct usb_msosv1_descriptor {
uint8_t vendor_code;
const uint8_t *compat_id;
const uint8_t **comp_id_property;
+ uint16_t comp_id_property_count; /* Number of entries; zero disables property requests. */
};
/* MS OS 2.0 Header descriptor */
diff --git a/common/usb_log.h b/common/usb_log.h
index ca03af5b..a1bc501c 100644
--- a/common/usb_log.h
+++ b/common/usb_log.h
@@ -95,8 +95,21 @@
} \
} while (false)
#else
-#define USB_ASSERT(f) {}
-#define USB_ASSERT_MSG(f, fmt, ...) {}
+#define USB_ASSERT(f) \
+ do { \
+ if (!(f)) { \
+ while (1) { \
+ } \
+ } \
+ } while (false)
+
+#define USB_ASSERT_MSG(f, fmt, ...) \
+ do { \
+ if (!(f)) { \
+ while (1) { \
+ } \
+ } \
+ } while (false)
#endif
#define ___is_print(ch) ((unsigned int)((ch) - ' ') < 127u - ' ')
diff --git a/core/usbd_core.c b/core/usbd_core.c
index b023fefc..c7850e67 100644
--- a/core/usbd_core.c
+++ b/core/usbd_core.c
@@ -29,6 +29,9 @@
#define INTF_DESC_bInterfaceNumber 2 /** Interface number offset */
#define INTF_DESC_bAlternateSetting 3 /** Alternate setting offset */
+#define CONFIG_USBDEV_MAX_EPS 16
+#define CONFIG_USBDEV_MAX_INTERFACES 16
+
struct usbd_tx_rx_msg {
uint8_t ep;
uint8_t ep_type;
@@ -78,12 +81,12 @@ USB_NOCACHE_RAM_SECTION struct usbd_core_priv {
usb_osal_mq_t usbd_ep0_mq;
usb_osal_thread_t usbd_ep0_thread;
#endif
- struct usbd_interface *intf[16];
- uint8_t intf_altsetting[16];
+ struct usbd_interface *intf[CONFIG_USBDEV_MAX_INTERFACES];
+ uint8_t intf_altsetting[CONFIG_USBDEV_MAX_INTERFACES];
uint8_t intf_offset;
- struct usbd_tx_rx_msg tx_msg[16];
- struct usbd_tx_rx_msg rx_msg[16];
+ struct usbd_tx_rx_msg tx_msg[CONFIG_USBDEV_MAX_EPS];
+ struct usbd_tx_rx_msg rx_msg[CONFIG_USBDEV_MAX_EPS];
void (*event_handler)(uint8_t busid, uint8_t event);
} g_usbd_core[CONFIG_USBDEV_MAX_BUS];
@@ -532,13 +535,19 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
break;
case USB_DESCRIPTOR_TYPE_ENDPOINT:
- if (cur_iface == iface) {
+ if (cur_iface == iface && if_desc != NULL) {
ep_desc = (struct usb_endpoint_descriptor *)p;
if (alt_setting == 0) {
ret = usbd_reset_endpoint(busid, ep_desc);
+ if (ret == false) {
+ return ret;
+ }
} else if (cur_alt_setting == alt_setting) {
ret = usbd_set_endpoint(busid, ep_desc);
+ if (ret == false) {
+ return ret;
+ }
if (g_usbd_core[busid].speed >= USB_SPEED_SUPER) {
const uint8_t *ep_comp_desc;
@@ -570,7 +579,9 @@ static bool usbd_set_interface(uint8_t busid, uint8_t iface, uint8_t alt_setting
}
}
- usbd_class_event_notify_handler(busid, USBD_EVENT_SET_INTERFACE, (void *)if_desc);
+ if (if_desc) {
+ usbd_class_event_notify_handler(busid, USBD_EVENT_SET_INTERFACE, (void *)if_desc);
+ }
return ret;
}
@@ -687,9 +698,11 @@ static bool usbd_std_device_req_handler(uint8_t busid, struct usb_setup_packet *
ret = false;
break;
case USB_REQUEST_SET_SEL:
+ *len = 0;
break;
case USB_REQUEST_SET_ISOCH_DLY:
g_usbd_core[busid].isoch_delay = value;
+ *len = 0;
break;
default:
@@ -720,6 +733,10 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
uint32_t current_desc_len = 0;
uint8_t cur_iface = 0xFF;
+ if (intf_num >= g_usbd_core[busid].intf_offset) {
+ return false;
+ }
+
p = g_usbd_core[busid].descriptors->config_descriptor_callback(g_usbd_core[busid].speed);
/* Only when device is configured, then interface requests can be valid. */
@@ -791,8 +808,12 @@ static bool usbd_std_interface_req_handler(uint8_t busid, struct usb_setup_packe
break;
case USB_REQUEST_SET_INTERFACE:
+ ret = usbd_set_interface(busid, intf_num, setup->wValue);
+ if (ret == false) {
+ break;
+ }
g_usbd_core[busid].intf_altsetting[intf_num] = LO_BYTE(setup->wValue);
- usbd_set_interface(busid, setup->wIndex, setup->wValue);
+
*len = 0;
break;
@@ -825,6 +846,10 @@ static bool usbd_std_endpoint_req_handler(uint8_t busid, struct usb_setup_packet
return false;
}
+ if ((ep & 0x7f) >= CONFIG_USBDEV_MAX_EPS) {
+ return false;
+ }
+
switch (setup->bRequest) {
case USB_REQUEST_GET_STATUS:
usbd_ep_is_stalled(busid, ep, &stalled);
@@ -963,21 +988,19 @@ static int usbd_vendor_request_handler(uint8_t busid, struct usb_setup_packet *s
if (setup->bRequest == g_usbd_core[busid].descriptors->msosv1_descriptor->vendor_code) {
switch (setup->wIndex) {
case 0x04:
- desclen = g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[0] +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[1] << 8) +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[2] << 16) +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id[3] << 24);
-
+ desclen = GET_LE32(g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id);
*data = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id;
//memcpy(*data, g_usbd_core[busid].descriptors->msosv1_descriptor->compat_id, desclen);
*len = desclen;
return 0;
case 0x05:
- desclen = g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][0] +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][1] << 8) +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][2] << 16) +
- (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue][3] << 24);
+ if (g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property == NULL ||
+ setup->wValue >= g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property_count ||
+ g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue] == NULL) {
+ return -1;
+ }
+ desclen = GET_LE32(g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue]);
*data = (uint8_t *)g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue];
//memcpy(*data, g_usbd_core[busid].descriptors->msosv1_descriptor->comp_id_property[setup->wValue], desclen);
*len = desclen;
@@ -1367,6 +1390,8 @@ void usbd_desc_register(uint8_t busid, const struct usb_descriptor *desc)
void usbd_add_interface(uint8_t busid, struct usbd_interface *intf)
{
+ USB_ASSERT_MSG(g_usbd_core[busid].intf_offset < CONFIG_USBDEV_MAX_INTERFACES, "Too many interfaces\r\n");
+
intf->intf_num = g_usbd_core[busid].intf_offset;
g_usbd_core[busid].intf[g_usbd_core[busid].intf_offset] = intf;
g_usbd_core[busid].intf_offset++;
diff --git a/core/usbh_core.c b/core/usbh_core.c
index ba00d8f8..0457a7c5 100644
--- a/core/usbh_core.c
+++ b/core/usbh_core.c
@@ -27,6 +27,7 @@ struct usbh_bus g_usbhost_bus[CONFIG_USBHOST_MAX_BUS];
#define DESC_bLength 0 /** Length offset */
#define DESC_bDescriptorType 1 /** Descriptor type offset */
+#define USB_DEV_ADDR_MIN 2
#define USB_DEV_ADDR_MAX 0x7f
#define USB_DEV_ADDR_MARK_OFFSET 5
#define USB_DEV_ADDR_MARK_MASK 0x1f
@@ -43,17 +44,19 @@ static void dummy_event_handler(uint8_t busid, uint8_t hub_index, uint8_t hub_po
static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
{
uint8_t lastaddr = devgen->last;
- uint8_t devaddr = lastaddr;
+ uint8_t devaddr;
int index;
int bitno;
+ if (lastaddr < USB_DEV_ADDR_MIN || lastaddr > USB_DEV_ADDR_MAX) {
+ lastaddr = USB_DEV_ADDR_MAX;
+ }
+ devaddr = lastaddr;
+
for (;;) {
devaddr++;
- if (devaddr > 0x7f) {
- devaddr = 2;
- }
- if (devaddr == lastaddr) {
- return -USB_ERR_NOMEM;
+ if (devaddr > USB_DEV_ADDR_MAX) {
+ devaddr = USB_DEV_ADDR_MIN;
}
index = devaddr >> 5;
@@ -63,6 +66,10 @@ static int usbh_allocate_devaddr(struct usbh_devaddr_map *devgen)
devgen->last = devaddr;
return (int)devaddr;
}
+
+ if (devaddr == lastaddr) {
+ return -USB_ERR_NOMEM;
+ }
}
}
@@ -71,7 +78,7 @@ static int __usbh_free_devaddr(struct usbh_devaddr_map *devgen, uint8_t devaddr)
int index;
int bitno;
- if ((devaddr > 0) && (devaddr < USB_DEV_ADDR_MAX)) {
+ if ((devaddr > 0) && (devaddr <= USB_DEV_ADDR_MAX)) {
index = devaddr >> USB_DEV_ADDR_MARK_OFFSET;
bitno = devaddr & USB_DEV_ADDR_MARK_MASK;
@@ -132,6 +139,10 @@ static const struct usbh_class_driver *usbh_find_class_driver(uint8_t class, uin
static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device_descriptor *desc, uint16_t length)
{
+ if (length < 8) {
+ return -USB_ERR_INVAL;
+ }
+
if (desc->bLength != USB_SIZEOF_DEVICE_DESC) {
USB_LOG_ERR("invalid device bLength 0x%02x\r\n", desc->bLength);
return -USB_ERR_INVAL;
@@ -139,6 +150,16 @@ static int parse_device_descriptor(struct usbh_hubport *hport, struct usb_device
USB_LOG_ERR("unexpected device descriptor 0x%02x\r\n", desc->bDescriptorType);
return -USB_ERR_INVAL;
} else {
+ if ((hport->speed >= USB_SPEED_SUPER && desc->bMaxPacketSize0 != 9) ||
+ (hport->speed == USB_SPEED_HIGH && desc->bMaxPacketSize0 != 64) ||
+ (hport->speed == USB_SPEED_LOW && desc->bMaxPacketSize0 != 8) ||
+ (hport->speed == USB_SPEED_FULL &&
+ desc->bMaxPacketSize0 != 8 && desc->bMaxPacketSize0 != 16 &&
+ desc->bMaxPacketSize0 != 32 && desc->bMaxPacketSize0 != 64)) {
+ USB_LOG_ERR("invalid bMaxPacketSize0 %d\r\n", desc->bMaxPacketSize0);
+ return -USB_ERR_INVAL;
+ }
+
if (length <= 8) {
return 0;
}
@@ -188,6 +209,9 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
uint32_t desc_len = 0;
uint8_t *p;
+ if (length < USB_SIZEOF_CONFIG_DESC) {
+ return -USB_ERR_INVAL;
+ }
if (desc->bLength != USB_SIZEOF_CONFIG_DESC) {
USB_LOG_ERR("invalid config bLength 0x%02x\r\n", desc->bLength);
return -USB_ERR_INVAL;
@@ -195,9 +219,17 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
USB_LOG_ERR("unexpected config descriptor 0x%02x\r\n", desc->bDescriptorType);
return -USB_ERR_INVAL;
} else {
+ if (desc->bNumInterfaces > CONFIG_USBHOST_MAX_INTERFACES) {
+ return -USB_ERR_NOMEM;
+ }
+
if (length <= USB_SIZEOF_CONFIG_DESC) {
return 0;
}
+
+ if (desc->wTotalLength != length) {
+ return -USB_ERR_INVAL;
+ }
#if 0
USB_LOG_DBG("Config Descriptor:\r\n");
USB_LOG_DBG("bLength: 0x%02x \r\n", desc->bLength);
@@ -225,9 +257,14 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
memset(hport->config.intf, 0, sizeof(struct usbh_interface) * CONFIG_USBHOST_MAX_INTERFACES);
- while (p[DESC_bLength]) {
+ while ((desc_len < length) &&
+ (p[DESC_bLength] >= 2) &&
+ (p[DESC_bLength] <= length - desc_len)) {
switch (p[DESC_bDescriptorType]) {
case USB_DESCRIPTOR_TYPE_INTERFACE:
+ if (cur_ep != cur_ep_num) {
+ return -USB_ERR_INVAL;
+ }
if (p[DESC_bLength] < USB_SIZEOF_INTERFACE_DESC) {
return -USB_ERR_INVAL;
}
@@ -242,16 +279,19 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
return -USB_ERR_NOMEM;
}
- if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
- USB_LOG_ERR("Endpoint num %d overflow\r\n", cur_ep_num);
+ if (cur_alt_setting >= CONFIG_USBHOST_MAX_INTF_ALTSETTINGS) {
+ USB_LOG_ERR("Interface altsetting num %d overflow\r\n", cur_alt_setting);
return -USB_ERR_NOMEM;
}
- if (cur_alt_setting >= CONFIG_USBHOST_MAX_INTF_ALTSETTINGS) {
- USB_LOG_ERR("Interface altsetting num %d overflow\r\n", cur_alt_setting);
+ if (cur_ep_num > CONFIG_USBHOST_MAX_ENDPOINTS) {
+ USB_LOG_ERR("Endpoint num %d overflow\r\n", cur_ep_num);
return -USB_ERR_NOMEM;
}
+ if (cur_alt_setting != hport->config.intf[cur_iface].altsetting_num) {
+ return -USB_ERR_INVAL;
+ }
#if 0
USB_LOG_DBG("Interface Descriptor:\r\n");
USB_LOG_DBG("bLength: 0x%02x \r\n", intf_desc->bLength);
@@ -264,8 +304,9 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
USB_LOG_DBG("bInterfaceProtocol: 0x%02x \r\n", intf_desc->bInterfaceProtocol);
USB_LOG_DBG("iInterface: 0x%02x \r\n", intf_desc->iInterface);
#endif
- memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].intf_desc, intf_desc, 9);
- hport->config.intf[cur_iface].altsetting_num = cur_alt_setting + 1;
+
+ memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].intf_desc, intf_desc, USB_SIZEOF_INTERFACE_DESC);
+ hport->config.intf[cur_iface].altsetting_num++;
break;
case USB_DESCRIPTOR_TYPE_ENDPOINT:
if (p[DESC_bLength] < USB_SIZEOF_ENDPOINT_DESC) {
@@ -273,12 +314,29 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
}
ep_desc = (struct usb_endpoint_descriptor *)p;
- if (cur_ep >= CONFIG_USBHOST_MAX_ENDPOINTS) {
+ if (USB_GET_MAXPACKETSIZE(ep_desc->wMaxPacketSize) == 0) {
+ return -USB_ERR_INVAL;
+ }
+
+ if ((ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_INTERRUPT ||
+ (ep_desc->bmAttributes & USB_ENDPOINT_TYPE_MASK) == USB_ENDPOINT_TYPE_ISOCHRONOUS) {
+ if (ep_desc->bInterval == 0 ||
+ (hport->speed >= USB_SPEED_HIGH && ep_desc->bInterval > 16)) {
+ return -USB_ERR_INVAL;
+ }
+ }
+
+ if (cur_iface >= CONFIG_USBHOST_MAX_INTERFACES) {
+ USB_LOG_ERR("Interface num %d overflow\r\n", cur_iface);
+ return -USB_ERR_NOMEM;
+ }
+
+ if (cur_ep >= cur_ep_num) {
USB_LOG_ERR("Endpoint num %d overflow\r\n", cur_ep);
return -USB_ERR_NOMEM;
}
- memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].ep[cur_ep].ep_desc, ep_desc, 7);
+ memcpy(&hport->config.intf[cur_iface].altsetting[cur_alt_setting].ep[cur_ep].ep_desc, ep_desc, USB_SIZEOF_ENDPOINT_DESC);
cur_ep++;
break;
@@ -288,10 +346,10 @@ static int parse_config_descriptor(struct usbh_hubport *hport, struct usb_config
/* skip to next descriptor */
desc_len += p[DESC_bLength];
p += p[DESC_bLength];
+ }
- if (desc_len > length) {
- return -USB_ERR_INVAL;
- }
+ if (cur_ep != cur_ep_num) {
+ return -USB_ERR_INVAL;
}
if (desc_len != length) {
@@ -379,8 +437,8 @@ int usbh_enumerate(struct usbh_hubport *hport)
/* Extract the correct max packetsize from the device descriptor */
dev_desc = (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid];
- if (dev_desc->bcdUSB >= USB_3_0) {
- ep_mps = 1 << dev_desc->bMaxPacketSize0;
+ if (hport->speed >= USB_SPEED_SUPER) {
+ ep_mps = 1U << dev_desc->bMaxPacketSize0;
} else {
ep_mps = dev_desc->bMaxPacketSize0;
}
@@ -395,6 +453,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
/* Assign a function address to the device connected to this port */
dev_addr = usbh_allocate_devaddr(&hport->bus->devgen);
if (dev_addr < 0) {
+ ret = dev_addr;
USB_LOG_ERR("Failed to allocate devaddr,errorcode:%d\r\n", ret);
goto errout;
}
@@ -409,6 +468,7 @@ int usbh_enumerate(struct usbh_hubport *hport)
ret = usbh_control_transfer(hport, setup, NULL);
if (ret < 0) {
USB_LOG_ERR("Failed to set devaddr,errorcode:%d\r\n", ret);
+ __usbh_free_devaddr(&hport->bus->devgen, (uint8_t)dev_addr);
goto errout;
}
@@ -431,7 +491,12 @@ int usbh_enumerate(struct usbh_hubport *hport)
goto errout;
}
- parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC);
+ ret = parse_device_descriptor(hport, (struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid], USB_SIZEOF_DEVICE_DESC);
+ if (ret < 0) {
+ USB_LOG_ERR("Parse full device descriptor fail\r\n");
+ goto errout;
+ }
+
USB_LOG_INFO("New device found,idVendor:%04x,idProduct:%04x,bcdDevice:%04x\r\n",
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idVendor,
((struct usb_device_descriptor *)ep0_request_buffer[hport->bus->busid])->idProduct,
@@ -748,17 +813,14 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
struct usb_setup_packet *setup = hport->setup;
int ret;
uint8_t *src;
- uint8_t *dst;
uint16_t len;
- uint16_t i = 2;
- uint16_t j = 0;
/* Get Manufacturer string */
setup->bmRequestType = USB_REQUEST_DIR_IN | USB_REQUEST_STANDARD | USB_REQUEST_RECIPIENT_DEVICE;
setup->bRequest = USB_REQUEST_GET_DESCRIPTOR;
setup->wValue = (uint16_t)((USB_DESCRIPTOR_TYPE_STRING << 8) | index);
setup->wIndex = 0x0409;
- setup->wLength = 255;
+ setup->wLength = MIN(255, CONFIG_USBHOST_REQUEST_BUFFER_LEN);
ret = usbh_control_transfer(hport, setup, ep0_request_buffer[hport->bus->busid]);
if (ret < 0) {
@@ -766,26 +828,19 @@ int usbh_get_string_desc(struct usbh_hubport *hport, uint8_t index, uint8_t *out
}
src = ep0_request_buffer[hport->bus->busid];
- dst = output;
- len = src[0];
-
- if (ret != len) {
- USB_LOG_ERR("Get string descriptor failed, expect %d, actual %d\r\n", len, ret);
+ if (ret < 2 || src[1] != USB_DESCRIPTOR_TYPE_STRING || src[0] != ret || (src[0] & 1)) {
return -USB_ERR_IO;
}
- memset(output, 0, output_len);
-
- if (((len - 2) / 2) > output_len) {
+ len = (src[0] - 2) / 2;
+ if (len > output_len) {
return -USB_ERR_NOMEM;
}
- while (i < len) {
- dst[j] = src[i];
- i += 2;
- j++;
+ memset(output, 0, output_len);
+ for (uint16_t i = 0; i < len; i++) {
+ output[i] = src[2 + 2 * i];
}
-
return 0;
}
diff --git a/demo/adb_template.c b/demo/adb_template.c
index 871d41a7..34715509 100644
--- a/demo/adb_template.c
+++ b/demo/adb_template.c
@@ -100,6 +100,7 @@ struct usb_msosv1_descriptor msosv1_desc = {
.vendor_code = WCID_VENDOR_CODE,
.compat_id = WINUSB_WCIDDescriptor,
.comp_id_property = WINUSB_IFx_WCIDProperties,
+ .comp_id_property_count = sizeof(WINUSB_IFx_WCIDProperties) / sizeof(WINUSB_IFx_WCIDProperties[0]),
};
static const uint8_t device_descriptor[] = {
diff --git a/demo/gs_usb_template.c b/demo/gs_usb_template.c
index b82c41c8..d6b533c1 100644
--- a/demo/gs_usb_template.c
+++ b/demo/gs_usb_template.c
@@ -74,6 +74,7 @@ struct usb_msosv1_descriptor linux_msosv1_desc = {
.vendor_code = LINUX_USBD_GS_CAN_VENDOR_CODE,
.compat_id = linux_WINUSB_WCIDDescriptor,
.comp_id_property = linux_WINUSB_IFx_WCIDProperties,
+ .comp_id_property_count = sizeof(linux_WINUSB_IFx_WCIDProperties) / sizeof(linux_WINUSB_IFx_WCIDProperties[0]),
};
static const uint8_t linux_device_descriptor[] = {
diff --git a/demo/mtp_template.c b/demo/mtp_template.c
index 11950d26..f42a3a57 100644
--- a/demo/mtp_template.c
+++ b/demo/mtp_template.c
@@ -194,6 +194,7 @@ struct usb_msosv1_descriptor msosv1_desc = {
.vendor_code = WCID_VENDOR_CODE,
.compat_id = WINUSB_WCIDDescriptor,
.comp_id_property = WINUSB_IFx_WCIDProperties,
+ .comp_id_property_count = sizeof(WINUSB_IFx_WCIDProperties) / sizeof(WINUSB_IFx_WCIDProperties[0]),
};
const struct usb_bos_descriptor bos_desc = {
diff --git a/demo/winusb1.0_template.c b/demo/winusb1.0_template.c
index 692bddc5..3fafe59e 100644
--- a/demo/winusb1.0_template.c
+++ b/demo/winusb1.0_template.c
@@ -106,6 +106,7 @@ struct usb_msosv1_descriptor msosv1_desc = {
.vendor_code = WINUSB_VENDOR_CODE,
.compat_id = WINUSB_WCIDDescriptor,
.comp_id_property = WINUSB_IFx_WCIDProperties,
+ .comp_id_property_count = sizeof(WINUSB_IFx_WCIDProperties) / sizeof(WINUSB_IFx_WCIDProperties[0]),
};
#define WINUSB_IN_EP 0x81
diff --git a/tools/test_srcipts/libusb_winusb_device_for_speed.c b/tools/test_srcipts/libusb_winusb_device_for_speed.c
index bcd02a03..d3ed01a5 100644
--- a/tools/test_srcipts/libusb_winusb_device_for_speed.c
+++ b/tools/test_srcipts/libusb_winusb_device_for_speed.c
@@ -72,6 +72,7 @@ struct usb_msosv1_descriptor msosv1_desc = {
.vendor_code = WCID_VENDOR_CODE,
.compat_id = WINUSB_WCIDDescriptor,
.comp_id_property = WINUSB_IFx_WCIDProperties,
+ .comp_id_property_count = sizeof(WINUSB_IFx_WCIDProperties) / sizeof(WINUSB_IFx_WCIDProperties[0]),
};
static const uint8_t device_descriptor[] = {