Message ID | 20190228122417.9318-1-louis@kragniz.eu (mailing list archive) |
---|---|
State | Superseded |
Headers | show |
Series | [v2] wusb: use correct format characters | expand |
On Thu, Feb 28, 2019 at 4:28 AM Louis Taylor <louis@kragniz.eu> wrote: > > When compiling with -Wformat, clang warns: > > ./include/linux/usb/wusb.h:245:5: warning: format specifies type > 'unsigned short' but the argument has type 'u8' (aka 'unsigned char') We should probably update Documentation/core-api/printk-formats.rst to list [u|s][8|16] printk formats so that I don't have to go read lib/vsprintf.c#format_decode(). (TODO in a separate patch) > [-Wformat] > ckhdid->data[0], ckhdid->data[1], > ^~~~~~~~~~~~~~~ > > ckhdid->data is unconditionally defined as `u8 data[16]`, so this patch > updates the format characters to the correct one for unsigned char types. > > Link: https://github.com/ClangBuiltLinux/linux/issues/378 > Signed-off-by: Louis Taylor <louis@kragniz.eu> > --- > include/linux/usb/wusb.h | 4 ++-- > 1 file changed, 2 insertions(+), 2 deletions(-) > > diff --git a/include/linux/usb/wusb.h b/include/linux/usb/wusb.h > index 9e4a3213f2c2..625366d3499e 100644 > --- a/include/linux/usb/wusb.h > +++ b/include/linux/usb/wusb.h > @@ -240,8 +240,8 @@ static inline size_t ckhdid_printf(char *pr_ckhdid, size_t size, > const struct wusb_ckhdid *ckhdid) > { > return scnprintf(pr_ckhdid, size, > - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx " > - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx", > + "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx " > + "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx", Looks like lib/vsprintf.c#format_decode() accepts either %hh or %H for lone unsigned bytes, IIUC. Thanks for the patch and for following up on the feedback. Reviewed-by: Nick Desaulniers <ndesaulniers@google.com> I wonder if __attribute__((packed)) is needed on the definition of `struct wusb_ckhdid`? hmm... via Stephen: https://godbolt.org/z/vs5JNo Looks like alignof(struct wusb_ckhdid) is 1. And struct wusb_ckhdid was introduced as is in commit c7f736484f8e ("wusb: add the Wireless USB include files.") so it's not like it ever had additional members that would disturb the alignment. `__aligned(__alignof__(u8))` might be clearer than `__attribute__((packed))`, but even then, I don't think anything is necessary since the alignof should always be 1? > ckhdid->data[0], ckhdid->data[1], > ckhdid->data[2], ckhdid->data[3], > ckhdid->data[4], ckhdid->data[5], > -- > 2.20.1 >
On Thu, 2019-02-28 at 12:24 +0000, Louis Taylor wrote: > When compiling with -Wformat, clang warns: > ./include/linux/usb/wusb.h:245:5: warning: format specifies type > 'unsigned short' but the argument has type 'u8' (aka 'unsigned char') > [-Wformat] > ckhdid->data[0], ckhdid->data[1], > ^~~~~~~~~~~~~~~ I think the message is somewhat misguided as all the vararg arguments have implicit integer promotions. > ckhdid->data is unconditionally defined as `u8 data[16]`, so this patch > updates the format characters to the correct one for unsigned char types. [] > diff --git a/include/linux/usb/wusb.h b/include/linux/usb/wusb.h [] > @@ -240,8 +240,8 @@ static inline size_t ckhdid_printf(char *pr_ckhdid, size_t size, > const struct wusb_ckhdid *ckhdid) > { > return scnprintf(pr_ckhdid, size, > - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx " > - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx", > + "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx " > + "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx", > ckhdid->data[0], ckhdid->data[1], > ckhdid->data[2], ckhdid->data[3], > ckhdid->data[4], ckhdid->data[5], Better to use the vsprintf %ph extension insead. --- include/linux/usb/wusb.h | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/include/linux/usb/wusb.h b/include/linux/usb/wusb.h index 9e4a3213f2c2..8c39ddf62951 100644 --- a/include/linux/usb/wusb.h +++ b/include/linux/usb/wusb.h @@ -239,17 +239,7 @@ enum { static inline size_t ckhdid_printf(char *pr_ckhdid, size_t size, const struct wusb_ckhdid *ckhdid) { - return scnprintf(pr_ckhdid, size, - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx " - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx", - ckhdid->data[0], ckhdid->data[1], - ckhdid->data[2], ckhdid->data[3], - ckhdid->data[4], ckhdid->data[5], - ckhdid->data[6], ckhdid->data[7], - ckhdid->data[8], ckhdid->data[9], - ckhdid->data[10], ckhdid->data[11], - ckhdid->data[12], ckhdid->data[13], - ckhdid->data[14], ckhdid->data[15]); + return scnprintf(pr_ckhdid, size, "%16ph", ckhdid->data); } /*
Thanks for the patch and comments. On Thu, Feb 28, 2019 at 1:53 PM Joe Perches <joe@perches.com> wrote: > > On Thu, 2019-02-28 at 12:24 +0000, Louis Taylor wrote: > > When compiling with -Wformat, clang warns: > > ./include/linux/usb/wusb.h:245:5: warning: format specifies type > > 'unsigned short' but the argument has type 'u8' (aka 'unsigned char') > > [-Wformat] > > ckhdid->data[0], ckhdid->data[1], > > ^~~~~~~~~~~~~~~ > > I think the message is somewhat misguided as all the > vararg arguments have implicit integer promotions. That's a fair point, but Clang checks the arguments against their format specifier before they're promoted when using -Wformat. When considering integer promotions it's difficult to say if this is "wrong", but since 'unsigned char' corresponds to the "hh" length specifier I don't think this is misguided. Otherwise, why use the "h" length specifier at all? > > > ckhdid->data is unconditionally defined as `u8 data[16]`, so this patch > > updates the format characters to the correct one for unsigned char types. > [] > > diff --git a/include/linux/usb/wusb.h b/include/linux/usb/wusb.h > [] > > @@ -240,8 +240,8 @@ static inline size_t ckhdid_printf(char *pr_ckhdid, size_t size, > > const struct wusb_ckhdid *ckhdid) > > { > > return scnprintf(pr_ckhdid, size, > > - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx " > > - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx", > > + "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx " > > + "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx", > > ckhdid->data[0], ckhdid->data[1], > > ckhdid->data[2], ckhdid->data[3], > > ckhdid->data[4], ckhdid->data[5], > > Better to use the vsprintf %ph extension insead. Agreed, so I guess my previous comment is irrelevant in this scenario. > --- > include/linux/usb/wusb.h | 12 +----------- > 1 file changed, 1 insertion(+), 11 deletions(-) > > diff --git a/include/linux/usb/wusb.h b/include/linux/usb/wusb.h > index 9e4a3213f2c2..8c39ddf62951 100644 > --- a/include/linux/usb/wusb.h > +++ b/include/linux/usb/wusb.h > @@ -239,17 +239,7 @@ enum { > static inline size_t ckhdid_printf(char *pr_ckhdid, size_t size, > const struct wusb_ckhdid *ckhdid) > { > - return scnprintf(pr_ckhdid, size, > - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx " > - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx", > - ckhdid->data[0], ckhdid->data[1], > - ckhdid->data[2], ckhdid->data[3], > - ckhdid->data[4], ckhdid->data[5], > - ckhdid->data[6], ckhdid->data[7], > - ckhdid->data[8], ckhdid->data[9], > - ckhdid->data[10], ckhdid->data[11], > - ckhdid->data[12], ckhdid->data[13], > - ckhdid->data[14], ckhdid->data[15]); > + return scnprintf(pr_ckhdid, size, "%16ph", ckhdid->data); > } > > /* > >
On Thu, 2019-02-28 at 14:23 -0800, Jon Flatley wrote: > Thanks for the patch and comments. > > On Thu, Feb 28, 2019 at 1:53 PM Joe Perches <joe@perches.com> wrote: > > On Thu, 2019-02-28 at 12:24 +0000, Louis Taylor wrote: > > > When compiling with -Wformat, clang warns: > > > ./include/linux/usb/wusb.h:245:5: warning: format specifies type > > > 'unsigned short' but the argument has type 'u8' (aka 'unsigned char') > > > [-Wformat] > > > ckhdid->data[0], ckhdid->data[1], > > > ^~~~~~~~~~~~~~~ > > > > I think the message is somewhat misguided as all the > > vararg arguments have implicit integer promotions. > > That's a fair point, but Clang checks the arguments against their > format specifier before they're promoted when using -Wformat. Perhaps clang could be a bit more verbose if checking signed types emitted as unsigned or unsigned types emitted as signed instead. > When > considering integer promotions it's difficult to say if this is > "wrong", I didn't write "wrong", I wrote misguided. > but since 'unsigned char' corresponds to the "hh" length > specifier I don't think this is misguided. Otherwise, why use the "h" > length specifier at all? e.g.: signed char as %x needs %hhx cheers, Joe
On Thu, Feb 28, 2019 at 3:05 PM Joe Perches <joe@perches.com> wrote: > > On Thu, 2019-02-28 at 14:23 -0800, Jon Flatley wrote: > > Thanks for the patch and comments. > > > > On Thu, Feb 28, 2019 at 1:53 PM Joe Perches <joe@perches.com> wrote: > > > On Thu, 2019-02-28 at 12:24 +0000, Louis Taylor wrote: > > > > When compiling with -Wformat, clang warns: > > > > ./include/linux/usb/wusb.h:245:5: warning: format specifies type > > > > 'unsigned short' but the argument has type 'u8' (aka 'unsigned char') > > > > [-Wformat] > > > > ckhdid->data[0], ckhdid->data[1], > > > > ^~~~~~~~~~~~~~~ > > > > > > I think the message is somewhat misguided as all the > > > vararg arguments have implicit integer promotions. > > > > That's a fair point, but Clang checks the arguments against their > > format specifier before they're promoted when using -Wformat. > > Perhaps clang could be a bit more verbose if > checking signed types emitted as unsigned or > unsigned types emitted as signed instead. It is a little strange that clang warns when the length specifier doesn't match but not when an unsigned specifier is used for a signed value and vice versa. > > > When > > considering integer promotions it's difficult to say if this is > > "wrong", > > I didn't write "wrong", I wrote misguided. Apologies for my poor wording. I meant "wrong" in the sense that it's unclear if an improper length specifier is deserving of a warning. After all GCC doesn't warn for incorrect length specifiers, and as you pointed out Clang doesn't pay attention to if the specifier expects a signed or unsigned value. Cheers, Jon
diff --git a/include/linux/usb/wusb.h b/include/linux/usb/wusb.h index 9e4a3213f2c2..625366d3499e 100644 --- a/include/linux/usb/wusb.h +++ b/include/linux/usb/wusb.h @@ -240,8 +240,8 @@ static inline size_t ckhdid_printf(char *pr_ckhdid, size_t size, const struct wusb_ckhdid *ckhdid) { return scnprintf(pr_ckhdid, size, - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx " - "%02hx %02hx %02hx %02hx %02hx %02hx %02hx %02hx", + "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx " + "%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx", ckhdid->data[0], ckhdid->data[1], ckhdid->data[2], ckhdid->data[3], ckhdid->data[4], ckhdid->data[5],
When compiling with -Wformat, clang warns: ./include/linux/usb/wusb.h:245:5: warning: format specifies type 'unsigned short' but the argument has type 'u8' (aka 'unsigned char') [-Wformat] ckhdid->data[0], ckhdid->data[1], ^~~~~~~~~~~~~~~ ckhdid->data is unconditionally defined as `u8 data[16]`, so this patch updates the format characters to the correct one for unsigned char types. Link: https://github.com/ClangBuiltLinux/linux/issues/378 Signed-off-by: Louis Taylor <louis@kragniz.eu> --- include/linux/usb/wusb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)