USB: Replace zero-length array with flexible-array member
Subsystems (10)
PATCH 1/1 USB: Replace zero-length array with flexible-array member
The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99:
struct foo {
int stuff;
struct boo array[];
};By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on.
Also, notice that, dynamic memory allocations won't be affected by this change:
"Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1]
This issue was found with the help of Coccinelle.
[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
[2] https://github.com/KSPP/linux/issues/21
[3] commit 76497732932f ("cxgb3/l2t: Fix undefined behaviour")
--- drivers/usb/atm/usbatm.h | 2 +- drivers/usb/dwc2/hcd.h | 2 +- drivers/usb/host/ehci-tegra.c | 2 +- drivers/usb/host/ehci.h | 4 ++-- drivers/usb/host/fotg210.h | 2 +- drivers/usb/host/ohci.h | 4 ++-- drivers/usb/host/xhci-mtk.h | 2 +- drivers/usb/host/xhci.h | 4 ++-- drivers/usb/serial/io_usbvend.h | 4 ++-- drivers/usb/serial/ti_usb_3410_5052.c | 4 ++-- include/linux/usb.h | 4 ++-- include/linux/usb/audio-v2.h | 2 +- include/linux/usb/audio-v3.h | 2 +- include/linux/usb/gadget.h | 2 +- include/linux/usb/hcd.h | 2 +- include/linux/usbdevice_fs.h | 2 +- 16 files changed, 22 insertions(+), 22 deletions(-)
drivers/usb/atm/usbatm.h +1 -1
@@ -164,7 +164,7 @@ struct usbatm_data {unsigned char *cell_buf;/* holds partial rx cell */ unsigned int buf_usage; -struct urb *urbs[0 ]; +struct urb *urbs[]; };static inline void *to_usbatm_driver_data (struct usb_interface *intf)
drivers/usb/dwc2/hcd.h +1 -1
@@ -199,7 +199,7 @@ struct dwc2_hcd_urb {u32 flags;u16 interval;struct dwc2_hcd_pipe_info pipe_info; -struct dwc2_hcd_iso_packet_desc iso_descs[0 ]; +struct dwc2_hcd_iso_packet_desc iso_descs[]; };/* Phases for control transfers */
drivers/usb/host/ehci-tegra.c +1 -1
@@ -282,7 +282,7 @@ static int tegra_ehci_hub_control(struct dma_aligned_buffer {void *kmalloc_ptr;void *old_xfer_buffer; -u8 data[0 ]; +u8 data[]; };static void free_dma_aligned_buffer (struct urb *urb)
drivers/usb/host/ehci.h +2 -2
@@ -255,7 +255,7 @@ struct ehci_hcd { /* one per controller */struct list_head tt_list;/* platform-specific data -- must come last */ -unsigned long priv[0 ]__aligned(sizeof(s64)) ; +unsigned long priv[]__aligned(sizeof(s64)) ; };/* convert between an HCD pointer and the corresponding EHCI_HCD */
@@ -460,7 +460,7 @@ struct ehci_iso_sched {struct list_head td_list;unsigned span;unsigned first_packet; -struct ehci_iso_packet packet[0 ]; +struct ehci_iso_packet packet[]; };/*
drivers/usb/host/fotg210.h +1 -1
@@ -490,7 +490,7 @@ struct fotg210_iso_packet {struct fotg210_iso_sched {struct list_head td_list;unsigned span; -struct fotg210_iso_packet packet[0 ]; +struct fotg210_iso_packet packet[]; };/*
drivers/usb/host/ohci.h +2 -2
@@ -337,7 +337,7 @@ typedef struct urb_priv {u16 length;// # tds in this request u16 td_cnt;// tds already serviced struct list_head pending; -struct td *td [0 ];// all TDs in this request +struct td *td[];// all TDs in this request } urb_priv_t;
@@ -435,7 +435,7 @@ struct ohci_hcd {struct dentry *debug_dir;/* platform-specific data -- must come last */ -unsigned long priv[0 ]__aligned(sizeof(s64)) ; +unsigned long priv[]__aligned(sizeof(s64)) ; };
drivers/usb/host/xhci-mtk.h +1 -1
@@ -95,7 +95,7 @@ struct mu3h_sch_ep_info {u32 pkts;u32 cs_count;u32 burst_mode; -u32 bw_budget_table[0 ]; +u32 bw_budget_table[]; };#define MU3C_U3_PORT_MAX 4
drivers/usb/host/xhci.h +2 -2
@@ -1642,7 +1642,7 @@ struct xhci_scratchpad {struct urb_priv {int num_tds;int num_tds_done; -struct xhci_td td[0 ]; +struct xhci_td td[]; };/*
@@ -1901,7 +1901,7 @@ struct xhci_hcd {void *dbc;/* platform-specific data -- must come last */ -unsigned long priv[0 ]__aligned(sizeof(s64)) ; +unsigned long priv[]__aligned(sizeof(s64)) ; };/* Platform specific overrides to generic XHCI hc_driver ops */
drivers/usb/serial/io_usbvend.h +2 -2
@@ -593,7 +593,7 @@ struct ti_i2c_desc {__u8 Type;// Type of descriptor __le16 Size;// Size of data only not including header __u8 CheckSum;// Checksum (8 bit sum of data only) -__u8 Data[0 ];// Data starts here +__u8 Data[];// Data starts here } __attribute__((packed));// for 5152 devices only (type 2 record)
@@ -601,7 +601,7 @@ struct ti_i2c_desc {struct ti_i2c_firmware_rec {__u8 Ver_Major;// Firmware Major version number __u8 Ver_Minor;// Firmware Minor version number -__u8 Data[0 ];// Download starts here +__u8 Data[];// Download starts here } __attribute__((packed));
drivers/usb/serial/ti_usb_3410_5052.c +2 -2
@@ -219,7 +219,7 @@ struct ti_write_data_bytes {u8 bDataCounter;__be16 wBaseAddrHi;__be16 wBaseAddrLo; -u8 bData[0 ]; +u8 bData[]; } __packed;struct ti_read_data_request {
@@ -234,7 +234,7 @@ struct ti_read_data_bytes {__u8 bCmdCode;__u8 bModuleId;__u8 bErrorCode; -__u8 bData[0 ]; +__u8 bData[]; } __packed;/* Interrupt struct */
include/linux/usb.h +2 -2
@@ -325,7 +325,7 @@ struct usb_interface_cache {/* variable-length array of alternate settings for this interface, * stored in no particular order */ -struct usb_host_interface altsetting[0 ]; +struct usb_host_interface altsetting[]; };#define ref_to_usb_interface_cache (r) \ container_of(r, struct usb_interface_cache, ref)
@@ -1589,7 +1589,7 @@ struct urb {int error_count;/* (return) number of ISO errors */ void *context;/* (in) context for completion */ usb_complete_t complete;/* (in) completion routine */ -struct usb_iso_packet_descriptor iso_frame_desc[0 ]; +struct usb_iso_packet_descriptor iso_frame_desc[];/* (in) ISO ONLY */ };
include/linux/usb/audio-v2.h +1 -1
@@ -153,7 +153,7 @@ struct uac2_feature_unit_descriptor {__u8 bSourceID;/* bmaControls is actually u32, * but u8 is needed for the hybrid parser */ -__u8 bmaControls[0 ];/* variable length */ +__u8 bmaControls[];/* variable length */ } __attribute__((packed));/* 4.7.2.10 Effect Unit Descriptor */
include/linux/usb/audio-v3.h +1 -1
@@ -109,7 +109,7 @@ struct uac3_feature_unit_descriptor {__u8 bSourceID;/* bmaControls is actually u32, * but u8 is needed for the hybrid parser */ -__u8 bmaControls[0 ];/* variable length */ +__u8 bmaControls[];/* variable length */ /* wFeatureDescrStr omitted */ } __attribute__((packed));
include/linux/usb/gadget.h +1 -1
@@ -767,7 +767,7 @@ struct usb_gadget_strings {struct usb_gadget_string_container {struct list_head list; -u8 *stash[0 ]; +u8 *stash[]; };/* put descriptor for string with that id into buf (buflen >= 256) */
include/linux/usb/hcd.h +1 -1
@@ -228,7 +228,7 @@ struct usb_hcd {/* The HC driver's private data is stored at the end of * this structure. */ - unsigned long hcd_priv[0] + unsigned long hcd_priv[] __attribute__ ((aligned(sizeof(s64)))); };
include/linux/usbdevice_fs.h +1 -1
@@ -69,7 +69,7 @@ struct usbdevfs_urb32 {compat_int_t error_count;compat_uint_t signr;compat_caddr_t usercontext;/* unused */ -struct usbdevfs_iso_packet_desc iso_frame_desc[0 ]; +struct usbdevfs_iso_packet_desc iso_frame_desc[]; };struct usbdevfs_ioctl32 {
Signature · 1 line
2.25.0
Johan Hovold
maintainerQuoted 39 lines · Gustavo A. R. Silva
The current codebase makes use of the zero-length array language extension to the C90 standard, but the preferred mechanism to declare variable-length types such as these ones is a flexible array member[1][2], introduced in C99:
struct foo { int stuff; struct boo array[]; };By making use of the mechanism above, we will get a compiler warning in case the flexible array does not occur last in the structure, which will help us prevent some kind of undefined behavior bugs from being inadvertently introduced[3] to the codebase from now on.
Also, notice that, dynamic memory allocations won't be affected by this change:
"Flexible array members have incomplete type, and so the sizeof operator may not be applied. As a quirk of the original implementation of zero-length arrays, sizeof evaluates to zero."[1]
This issue was found with the help of Coccinelle.
[1] https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
[2] https://github.com/KSPP/linux/issues/21
[3] commit76497732932f("cxgb3/l2t: Fix undefined behaviour")Signed-off-by Gustavo A. R. Silva <gustavo-L1vi/[email protected]>--- drivers/usb/atm/usbatm.h | 2 +- drivers/usb/dwc2/hcd.h | 2 +- drivers/usb/host/ehci-tegra.c | 2 +- drivers/usb/host/ehci.h | 4 ++-- drivers/usb/host/fotg210.h | 2 +- drivers/usb/host/ohci.h | 4 ++-- drivers/usb/host/xhci-mtk.h | 2 +- drivers/usb/host/xhci.h | 4 ++-- drivers/usb/serial/io_usbvend.h | 4 ++--
Quoted 8 lines
drivers/usb/serial/ti_usb_3410_5052.c | 4 ++-- include/linux/usb.h | 4 ++-- include/linux/usb/audio-v2.h | 2 +- include/linux/usb/audio-v3.h | 2 +- include/linux/usb/gadget.h | 2 +- include/linux/usb/hcd.h | 2 +- include/linux/usbdevice_fs.h | 2 +- 16 files changed, 22 insertions(+), 22 deletions(-)
Looks like your scripts still doesn't catch every instance. A simple grep like
git grep -A1 '\[0\];$' drivers/usb/ | grep -B1 '}'
found at least three more in
drivers/usb/atm/ueagle-atm.c
drivers/usb/gadget/function/f_phonet.c
drivers/usb/musb/musb_host.c
Johan