When compiling with gcc 12 drivers/usb.c generates the following error:
/root/drivers/usb.c: In function 'get_descriptor': /root/drivers/usb.c:200:23: error: array subscript 'device_descriptor_t[0]' is partly outside array bounds of 'u8[8]' {aka 'unsigned char[8]'} [-Werror=array-bounds] 200 | if (dd->bMaxPacketSize0 != 0) | ^~ /root/drivers/usb.c:181:12: note: object 'buf' of size 8 181 | u8 buf[8]; | ^~~ cc1: all warnings being treated as errors make[1]: *** [rules.mak:229: target/drivers/usb.o] Error 1 make[1]: Leaving directory '/root/obj-ppc'
The compiler is complaining that a device_descriptor_t pointer cast to the 8 byte buffer means that a pointer dereference to some members of the device_descriptor_t could go beyond the end of the 8 byte buffer. Whilst this sounds as if it should be allowed, some searching suggests that the behaviour of such a cast is undefined.
Rework get_descriptor() so that an entire device_descriptor_t is used to store the first 8 bytes of the incoming descriptor, and update the buf references to use the equivalent device_descriptor_t fields instead.
Signed-off-by: Mark Cave-Ayland mark.cave-ayland@ilande.co.uk --- drivers/usb.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/usb.c b/drivers/usb.c index 88b7580..d0e1ae5 100644 --- a/drivers/usb.c +++ b/drivers/usb.c @@ -178,7 +178,7 @@ u8 * get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType, int descIdx, int langID) { - u8 buf[8]; + device_descriptor_t dd; u8 *result; dev_req_t dr; int size; @@ -189,24 +189,23 @@ get_descriptor (usbdev_t *dev, unsigned char bmRequestType, int descType, dr.wValue = __cpu_to_le16((descType << 8) | descIdx); dr.wIndex = __cpu_to_le16(langID); dr.wLength = __cpu_to_le16(8); - if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, buf)) { + if (dev->controller->control (dev, IN, sizeof (dr), &dr, 8, (u8 *)&dd)) { usb_debug ("getting descriptor size (type %x) failed\n", descType); }
if (descType == 1) { - device_descriptor_t *dd = (device_descriptor_t *) buf; - usb_debug ("maxPacketSize0: %x\n", dd->bMaxPacketSize0); - if (dd->bMaxPacketSize0 != 0) - dev->endpoints[0].maxpacketsize = dd->bMaxPacketSize0; + usb_debug ("maxPacketSize0: %x\n", dd.bMaxPacketSize0); + if (dd.bMaxPacketSize0 != 0) + dev->endpoints[0].maxpacketsize = dd.bMaxPacketSize0; }
/* special case for configuration descriptors: they carry all their subsequent descriptors with them, and keep the entire size at a different location */ - size = buf[0]; - if (buf[1] == 2) { - int realsize = __le16_to_cpu(((unsigned short *) (buf + 2))[0]); + size = dd.bLength; + if (dd.bDescriptorType == 2) { + int realsize = __le16_to_cpu(dd.bcdUSB); size = realsize; } result = malloc (size);