Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bounded flexible arrays: tag their element count #1409

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 18 additions & 4 deletions libusb/libusb.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,20 @@ typedef SSIZE_T ssize_t;
#define LIBUSB_FLEXIBLE_ARRAY 0 /* [0] - non-standard, but usually working code */
#endif /* __STDC_VERSION__ */

/* gcc > 14 and clang > 17 support the counted_by attribute,
* used to indicate the size of struct flexible array members.
* This helps detected buffer overruns.
* See: https://people.kernel.org/kees/bounded-flexible-arrays-in-c */
#if defined __has_attribute
#if __has_attribute(__counted_by__)
#define LIBUSB_COUNTED_BY(member) __attribute__((counted_by(member)))
#else
#define LIBUSB_COUNTED_BY(member)
#endif
#else
#define LIBUSB_COUNTED_BY(member)
#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 @@ -889,7 +903,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 @@ -914,7 +928,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 @@ -1130,7 +1144,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 @@ -1513,7 +1527,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 @@ -705,7 +705,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 @@ -919,7 +919,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
Loading