On Mon, Jul 01, 2013 at 12:02:45PM +0200, Hans de Goede wrote:
> Unaligned accesses on architectures which don't support it, either get
> trapped and emulated (with a fat warnign logged somewhere), or get trapped
> and terminate the program. So I don't think this may cause "subtle" bugs.

I agree that it's unlikely to be an issue in real life for libusb, but
I was tricked by exactly the same problem with uIP on an older ARM
microcontroller (ARM7/ARMv4T), it wasn't easy to debug at all.

Triggering subtle bugs here would require running uCLinux
(i.e. MMU-less) with libusb. This [1] document has an elaborate
description about the matters (in particular, LDR doing a "rotated load").

[1] http://www.heyrick.co.uk/armwiki/Unaligned_data_access

> Notice that actually getting the alignment wrong is pretty hard, most ABI's
> guarantee some stack pointer alignment when entering a function, so having
> an unaligned  buffer would require declaring vars like ie this:
>
> unsigned char unalign[3];
> unsigned char buffer[16];

Yep, certainly. And malloc() guarantees maximum alignment.

> Since you're actually getting the warnings can you provide a patch to silence
> them ?

Follows (against the current libusbx HEAD, but should be applicable to
libusb as well), TIA

From: Paul Fertser <fercer...@gmail.com>
Date: Mon, 1 Jul 2013 20:47:18 +0400
Subject: [PATCH] Clarify alignment requirements for the control transfer
 buffer

Since the buffer pointer will later be casted to ``struct
libusb_control_setup *'', it should point to memory aligned to at least
2 bytes boundary as that's the strictest requirement of the struct fields.

Also, use a (void *) casting trick to convince the compiler the cast is
safe, to fix warnings such as:

/usr/local/include/libusb-1.0/libusb.h: In function 
'libusb_control_transfer_get_setup':
/usr/local/include/libusb-1.0/libusb.h:1435:9: error: cast increases required 
alignment of target type [-Werror=cast-align]
/usr/local/include/libusb-1.0/libusb.h: In function 'libusb_fill_control_setup':
/usr/local/include/libusb-1.0/libusb.h:1464:39: error: cast increases required 
alignment of target type [-Werror=cast-align]
/usr/local/include/libusb-1.0/libusb.h: In function 
'libusb_fill_control_transfer':
/usr/local/include/libusb-1.0/libusb.h:1509:39: error: cast increases required 
alignment of target type [-Werror=cast-align]
cc1: all warnings being treated as errors

This actually can lead to failure to build from the sources for certain
projects which use -Werror=cast-align on ARM.

Signed-off-by: Paul Fertser <fercer...@gmail.com>
---
 libusb/io.c     |    2 +-
 libusb/libusb.h |    8 +++++---
 2 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/libusb/io.c b/libusb/io.c
index b27e082..add2328 100644
--- a/libusb/io.c
+++ b/libusb/io.c
@@ -731,7 +731,7 @@ void cb(struct libusb_transfer *transfer)
 
 void myfunc() {
        struct libusb_transfer *transfer;
-       unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE];
+       unsigned char buffer[LIBUSB_CONTROL_SETUP_SIZE] __attribute__ ((aligned 
(2)));
        int completed = 0;
 
        transfer = libusb_alloc_transfer(0);
diff --git a/libusb/libusb.h b/libusb/libusb.h
index 5e1c23c..2c98f52 100644
--- a/libusb/libusb.h
+++ b/libusb/libusb.h
@@ -1428,7 +1428,7 @@ static inline unsigned char 
*libusb_control_transfer_get_data(
 static inline struct libusb_control_setup *libusb_control_transfer_get_setup(
        struct libusb_transfer *transfer)
 {
-       return (struct libusb_control_setup *) transfer->buffer;
+       return (struct libusb_control_setup *)(void *) transfer->buffer;
 }
 
 /** \ingroup asyncio
@@ -1437,6 +1437,7 @@ static inline struct libusb_control_setup 
*libusb_control_transfer_get_setup(
  * be given in host-endian byte order.
  *
  * \param buffer buffer to output the setup packet into
+ * This pointer must be aligned to at least 2 bytes boundary.
  * \param bmRequestType see the
  * \ref libusb_control_setup::bmRequestType "bmRequestType" field of
  * \ref libusb_control_setup
@@ -1457,7 +1458,7 @@ static inline void libusb_fill_control_setup(unsigned 
char *buffer,
        uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t 
wIndex,
        uint16_t wLength)
 {
-       struct libusb_control_setup *setup = (struct libusb_control_setup *) 
buffer;
+       struct libusb_control_setup *setup = (struct libusb_control_setup 
*)(void *) buffer;
        setup->bmRequestType = bmRequestType;
        setup->bRequest = bRequest;
        setup->wValue = libusb_cpu_to_le16(wValue);
@@ -1493,6 +1494,7 @@ void LIBUSB_CALL libusb_free_transfer(struct 
libusb_transfer *transfer);
  * \param dev_handle handle of the device that will handle the transfer
  * \param buffer data buffer. If provided, this function will interpret the
  * first 8 bytes as a setup packet and infer the transfer length from that.
+ * This pointer must be aligned to at least 2 bytes boundary.
  * \param callback callback function to be invoked on transfer completion
  * \param user_data user data to pass to callback function
  * \param timeout timeout for the transfer in milliseconds
@@ -1502,7 +1504,7 @@ static inline void libusb_fill_control_transfer(
        unsigned char *buffer, libusb_transfer_cb_fn callback, void *user_data,
        unsigned int timeout)
 {
-       struct libusb_control_setup *setup = (struct libusb_control_setup *) 
buffer;
+       struct libusb_control_setup *setup = (struct libusb_control_setup 
*)(void *) buffer;
        transfer->dev_handle = dev_handle;
        transfer->endpoint = 0;
        transfer->type = LIBUSB_TRANSFER_TYPE_CONTROL;
-- 
1.7.9

------------------------------------------------------------------------------
This SF.net email is sponsored by Windows:

Build for Windows Store.

http://p.sf.net/sfu/windows-dev2dev
_______________________________________________
libusbx-devel mailing list
libusbx-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/libusbx-devel

Reply via email to