etc~ scripts and random things |
| git clone https://github.com/djnnvx/etc.git |
| log | files | refs | archive |
fuzz_usbfs_shim.c (3966B)
1 /* 2 * Extraction of parse_config_descriptors() + seek_to_next_config() from 3 * linux_usbfs.c. Verbatim logic, local type definitions, fuzz-visible entry point. 4 */ 5 6 #include "fuzz-include/libusb_fuzz.h" 7 #include "libusb-src/libusb/libusbi.h" 8 9 struct config_descriptor { 10 struct usbi_configuration_descriptor *desc; 11 size_t actual_len; 12 }; 13 14 struct linux_device_priv { 15 char *sysfs_dir; 16 void *descriptors; 17 size_t descriptors_len; 18 struct config_descriptor *config_descriptors; 19 int active_config; 20 }; 21 22 static int seek_to_next_config(struct libusb_context *ctx, 23 uint8_t *buffer, size_t len) 24 { 25 struct usbi_descriptor_header *header; 26 int offset = LIBUSB_DT_CONFIG_SIZE; 27 28 buffer += LIBUSB_DT_CONFIG_SIZE; 29 len -= LIBUSB_DT_CONFIG_SIZE; 30 31 while (len > 0) { 32 if (len < 2) { 33 usbi_err(ctx, "remaining descriptor length too small %zu/2", len); 34 return LIBUSB_ERROR_IO; 35 } 36 header = (struct usbi_descriptor_header *)buffer; 37 if (header->bDescriptorType == LIBUSB_DT_CONFIG) 38 return offset; 39 if (header->bLength < 2) { 40 usbi_err(ctx, "invalid descriptor bLength %hhu", header->bLength); 41 return LIBUSB_ERROR_IO; 42 } 43 if (len < header->bLength) { 44 usbi_err(ctx, "bLength overflow by %zu bytes", 45 (size_t)header->bLength - len); 46 return LIBUSB_ERROR_IO; 47 } 48 offset += header->bLength; 49 buffer += header->bLength; 50 len -= header->bLength; 51 } 52 53 usbi_err(ctx, "config descriptor not found"); 54 return LIBUSB_ERROR_IO; 55 } 56 57 int fuzz_parse_config_descriptors(struct libusb_device *dev) 58 { 59 struct libusb_context *ctx = DEVICE_CTX(dev); 60 struct linux_device_priv *priv = usbi_get_device_priv(dev); 61 struct usbi_device_descriptor *device_desc; 62 uint8_t idx, num_configs; 63 uint8_t *buffer; 64 size_t remaining; 65 66 device_desc = priv->descriptors; 67 num_configs = device_desc->bNumConfigurations; 68 if (num_configs == 0) 69 return 0; 70 71 priv->config_descriptors = malloc( 72 num_configs * sizeof(priv->config_descriptors[0])); 73 if (!priv->config_descriptors) 74 return LIBUSB_ERROR_NO_MEM; 75 76 buffer = (uint8_t *)priv->descriptors + LIBUSB_DT_DEVICE_SIZE; 77 remaining = priv->descriptors_len - LIBUSB_DT_DEVICE_SIZE; 78 79 for (idx = 0; idx < num_configs; idx++) { 80 struct usbi_configuration_descriptor *config_desc; 81 uint16_t config_len; 82 83 if (remaining < LIBUSB_DT_CONFIG_SIZE) { 84 usbi_err(ctx, "short descriptor read %zu/%d", 85 remaining, LIBUSB_DT_CONFIG_SIZE); 86 return LIBUSB_ERROR_IO; 87 } 88 89 config_desc = (struct usbi_configuration_descriptor *)buffer; 90 if (config_desc->bDescriptorType != LIBUSB_DT_CONFIG) { 91 usbi_err(ctx, "not a config descriptor (type 0x%02x)", 92 config_desc->bDescriptorType); 93 return LIBUSB_ERROR_IO; 94 } else if (config_desc->bLength < LIBUSB_DT_CONFIG_SIZE) { 95 usbi_err(ctx, "invalid descriptor bLength %u", config_desc->bLength); 96 return LIBUSB_ERROR_IO; 97 } 98 99 config_len = libusb_le16_to_cpu(config_desc->wTotalLength); 100 if (config_len < LIBUSB_DT_CONFIG_SIZE) { 101 usbi_err(ctx, "invalid wTotalLength %u", config_len); 102 return LIBUSB_ERROR_IO; 103 } 104 105 /* sysfs_dir == NULL → usbfs path: wTotalLength used directly */ 106 if (!priv->sysfs_dir) { 107 if (config_len > remaining) { 108 usbi_warn(ctx, "short descriptor read %zu/%u", remaining, config_len); 109 config_len = (uint16_t)remaining; 110 } 111 } 112 113 priv->config_descriptors[idx].desc = config_desc; 114 priv->config_descriptors[idx].actual_len = config_len; 115 buffer += config_len; 116 remaining -= config_len; 117 } 118 119 return LIBUSB_SUCCESS; 120 }