Skip to content

Commit

Permalink
Introduced LIBUSB_COUNTED_BY macro, which does nothing yet
Browse files Browse the repository at this point in the history
When/if gcc and clang add support for __attribute__ __element_count__ this will allow catching array overruns with UBSan.

See:
https://people.kernel.org/kees/bounded-flexible-arrays-in-c
  • Loading branch information
seanm committed Jan 20, 2024
1 parent b4f877f commit 3c19ac3
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 6 deletions.
18 changes: 14 additions & 4 deletions libusb/libusb.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,16 @@ typedef SSIZE_T ssize_t;
#define LIBUSB_FLEXIBLE_ARRAY 0 /* [0] - non-standard, but usually working code */
#endif /* __STDC_VERSION__ */

/* When gcc and/or clang eventually support the counted_by attribute,
* we can use this to indicate the size of struct flexible array members.
* which helps detected buffer overruns.
* See: https://people.kernel.org/kees/bounded-flexible-arrays-in-c */
#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)
#define LIBUSB_COUNTED_BY(x)
#else
#define LIBUSB_COUNTED_BY(x)
#endif

/* 'interface' might be defined as a macro on Windows, so we need to
* undefine it so as not to break the current libusb API, because
* libusb_config_descriptor has an 'interface' member
Expand Down Expand Up @@ -857,7 +867,7 @@ struct libusb_bos_dev_capability_descriptor {
uint8_t bDevCapabilityType;

/** Device Capability data (bLength - 3 bytes) */
uint8_t dev_capability_data[LIBUSB_FLEXIBLE_ARRAY];
uint8_t dev_capability_data[LIBUSB_FLEXIBLE_ARRAY] LIBUSB_COUNTED_BY(bLength - 3);
};

/** \ingroup libusb_desc
Expand All @@ -882,7 +892,7 @@ struct libusb_bos_descriptor {
uint8_t bNumDeviceCaps;

/** bNumDeviceCap Device Capability Descriptors */
struct libusb_bos_dev_capability_descriptor *dev_capability[LIBUSB_FLEXIBLE_ARRAY];
struct libusb_bos_dev_capability_descriptor *dev_capability[LIBUSB_FLEXIBLE_ARRAY] LIBUSB_COUNTED_BY(bNumDeviceCaps);
};

/** \ingroup libusb_desc
Expand Down Expand Up @@ -1004,7 +1014,7 @@ struct libusb_platform_descriptor {
uint8_t PlatformCapabilityUUID[16];

/** Capability data (bLength - 20) */
uint8_t CapabilityData[LIBUSB_FLEXIBLE_ARRAY];
uint8_t CapabilityData[LIBUSB_FLEXIBLE_ARRAY] LIBUSB_COUNTED_BY(bLength - 20);
};

/** \ingroup libusb_asyncio
Expand Down Expand Up @@ -1384,7 +1394,7 @@ struct libusb_transfer {
int num_iso_packets;

/** Isochronous packet descriptors, for isochronous transfers only. */
struct libusb_iso_packet_descriptor iso_packet_desc[LIBUSB_FLEXIBLE_ARRAY];
struct libusb_iso_packet_descriptor iso_packet_desc[LIBUSB_FLEXIBLE_ARRAY] LIBUSB_COUNTED_BY(num_iso_packets);
};

/** \ingroup libusb_misc
Expand Down
4 changes: 2 additions & 2 deletions libusb/libusbi.h
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,7 @@ struct usbi_interface_descriptor {
struct usbi_string_descriptor {
uint8_t bLength;
uint8_t bDescriptorType;
uint16_t wData[LIBUSB_FLEXIBLE_ARRAY];
uint16_t wData[LIBUSB_FLEXIBLE_ARRAY] LIBUSB_COUNTED_BY((bLength - 2) / 2);
} LIBUSB_PACKED;

struct usbi_bos_descriptor {
Expand Down Expand Up @@ -907,7 +907,7 @@ static inline void *usbi_get_transfer_priv(struct usbi_transfer *itransfer)
struct discovered_devs {
size_t len;
size_t capacity;
struct libusb_device *devices[LIBUSB_FLEXIBLE_ARRAY];
struct libusb_device *devices[LIBUSB_FLEXIBLE_ARRAY] LIBUSB_COUNTED_BY(len);
};

struct discovered_devs *discovered_devs_append(
Expand Down

0 comments on commit 3c19ac3

Please sign in to comment.