diff mbox series

[v3,1/2] vsprintf: Add %p[mM]U for uppercase MAC address

Message ID 20230427115120.241954-1-k.graefe@gateware.de (mailing list archive)
State Superseded
Headers show
Series [v3,1/2] vsprintf: Add %p[mM]U for uppercase MAC address | expand

Commit Message

Konrad Gräfe April 27, 2023, 11:51 a.m. UTC
The CDC-ECM specification requires an USB gadget to send the host MAC
address as uppercase hex string. This change adds the appropriate
modifier.

Cc: stable@vger.kernel.org
Signed-off-by: Konrad Gräfe <k.graefe@gateware.de>
---
Added in v3

 lib/vsprintf.c | 18 +++++++++++++++---
 1 file changed, 15 insertions(+), 3 deletions(-)

Comments

Greg KH April 27, 2023, 12:26 p.m. UTC | #1
On Thu, Apr 27, 2023 at 01:51:19PM +0200, Konrad Gräfe wrote:
> The CDC-ECM specification requires an USB gadget to send the host MAC
> address as uppercase hex string. This change adds the appropriate
> modifier.
> 
> Cc: stable@vger.kernel.org
> Signed-off-by: Konrad Gräfe <k.graefe@gateware.de>
> ---
> Added in v3
> 
>  lib/vsprintf.c | 18 +++++++++++++++---
>  1 file changed, 15 insertions(+), 3 deletions(-)
> 
> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index be71a03c936a..8aee1caabd9e 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -1269,9 +1269,10 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
>  {
>  	char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
>  	char *p = mac_addr;
> -	int i;
> +	int i, pos;
>  	char separator;
>  	bool reversed = false;
> +	bool uppercase = false;
>  
>  	if (check_pointer(&buf, end, addr, spec))
>  		return buf;
> @@ -1281,6 +1282,10 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
>  		separator = '-';
>  		break;
>  
> +	case 'U':
> +		uppercase = true;
> +		break;

No documentation update as well?

thanks,

greg k-h
Rasmus Villemoes April 27, 2023, 12:35 p.m. UTC | #2
On 27/04/2023 13.51, Konrad Gräfe wrote:
> The CDC-ECM specification requires an USB gadget to send the host MAC
> address as uppercase hex string. This change adds the appropriate
> modifier.
> 
> Cc: stable@vger.kernel.org

Why cc stable?

> Signed-off-by: Konrad Gräfe <k.graefe@gateware.de>
> ---
> Added in v3
> 
>  lib/vsprintf.c | 18 +++++++++++++++---
>  1 file changed, 15 insertions(+), 3 deletions(-)

The diffstat here, or for some other patch in the same series,
definitely ought to mention lib/test_printf.c.

> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> index be71a03c936a..8aee1caabd9e 100644
> --- a/lib/vsprintf.c
> +++ b/lib/vsprintf.c
> @@ -1269,9 +1269,10 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
>  {
>  	char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
>  	char *p = mac_addr;
> -	int i;
> +	int i, pos;
>  	char separator;
>  	bool reversed = false;
> +	bool uppercase = false;
>  
>  	if (check_pointer(&buf, end, addr, spec))
>  		return buf;
> @@ -1281,6 +1282,10 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
>  		separator = '-';
>  		break;
>  
> +	case 'U':
> +		uppercase = true;
> +		break;
> +
>  	case 'R':
>  		reversed = true;
>  		fallthrough;

This seems broken, and I'm surprised the compiler doesn't warn about
separator possibly being uninitialized further down. I'm also surprised
your testing hasn't caught this. For reference, the full switch
statement is currently

        switch (fmt[1]) {
        case 'F':
                separator = '-';
                break;

        case 'R':
                reversed = true;
                fallthrough;

        default:
                separator = ':';
                break;
        }

> @@ -1292,9 +1297,14 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
>  
>  	for (i = 0; i < 6; i++) {
>  		if (reversed)
> -			p = hex_byte_pack(p, addr[5 - i]);
> +			pos = 5 - i;
> +		else
> +			pos = i;
> +
> +		if (uppercase)
> +			p = hex_byte_pack_upper(p, addr[pos]);
>  		else
> -			p = hex_byte_pack(p, addr[i]);
> +			p = hex_byte_pack(p, addr[pos]);

I think this becomes quite hard to follow. We have string_upper() in
linux/string_helpers.h, so I'd rather just leave this loop alone and do

  if (uppercase)
    string_upper(mac_addr, mac_addr);

after the nul-termination.

Rasmus
Konrad Gräfe April 27, 2023, 2:26 p.m. UTC | #3
On 27.04.23 14:35, Rasmus Villemoes wrote:
> On 27/04/2023 13.51, Konrad Gräfe wrote:
>> The CDC-ECM specification requires an USB gadget to send the host MAC
>> address as uppercase hex string. This change adds the appropriate
>> modifier.
>>
>> Cc: stable@vger.kernel.org
> 
> Why cc stable?

I believe the second patch matches the criteria but it uses this one.

> 
>> Signed-off-by: Konrad Gräfe <k.graefe@gateware.de>
>> ---
>> Added in v3
>>
>>   lib/vsprintf.c | 18 +++++++++++++++---
>>   1 file changed, 15 insertions(+), 3 deletions(-)
> 
> The diffstat here, or for some other patch in the same series,
> definitely ought to mention lib/test_printf.c.
> 
>> diff --git a/lib/vsprintf.c b/lib/vsprintf.c
>> index be71a03c936a..8aee1caabd9e 100644
>> --- a/lib/vsprintf.c
>> +++ b/lib/vsprintf.c
>> @@ -1269,9 +1269,10 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
>>   {
>>   	char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
>>   	char *p = mac_addr;
>> -	int i;
>> +	int i, pos;
>>   	char separator;
>>   	bool reversed = false;
>> +	bool uppercase = false;
>>   
>>   	if (check_pointer(&buf, end, addr, spec))
>>   		return buf;
>> @@ -1281,6 +1282,10 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
>>   		separator = '-';
>>   		break;
>>   
>> +	case 'U':
>> +		uppercase = true;
>> +		break;
>> +
>>   	case 'R':
>>   		reversed = true;
>>   		fallthrough;
> 
> This seems broken, and I'm surprised the compiler doesn't warn about
> separator possibly being uninitialized further down. I'm also surprised
> your testing hasn't caught this. For reference, the full switch
> statement is currently
> 
>          switch (fmt[1]) {
>          case 'F':
>                  separator = '-';
>                  break;
> 
>          case 'R':
>                  reversed = true;
>                  fallthrough;
> 
>          default:
>                  separator = ':';
>                  break;
>          }
> 
>> @@ -1292,9 +1297,14 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
>>   
>>   	for (i = 0; i < 6; i++) {
>>   		if (reversed)
>> -			p = hex_byte_pack(p, addr[5 - i]);
>> +			pos = 5 - i;
>> +		else
>> +			pos = i;
>> +
>> +		if (uppercase)
>> +			p = hex_byte_pack_upper(p, addr[pos]);
>>   		else
>> -			p = hex_byte_pack(p, addr[i]);
>> +			p = hex_byte_pack(p, addr[pos]);
> 
> I think this becomes quite hard to follow. We have string_upper() in
> linux/string_helpers.h, so I'd rather just leave this loop alone and do
> 
>    if (uppercase)
>      string_upper(mac_addr, mac_addr);
> 
> after the nul-termination.
> 
> Rasmus
>
Peter Seiderer April 27, 2023, 9:30 p.m. UTC | #4
Hello Rasmus, Konrad, *,

On Thu, 27 Apr 2023 14:35:19 +0200, Rasmus Villemoes <linux@rasmusvillemoes.dk> wrote:

> On 27/04/2023 13.51, Konrad Gräfe wrote:
> > The CDC-ECM specification requires an USB gadget to send the host MAC
> > address as uppercase hex string. This change adds the appropriate
> > modifier.
> > 
> > Cc: stable@vger.kernel.org  
> 
> Why cc stable?
> 
> > Signed-off-by: Konrad Gräfe <k.graefe@gateware.de>
> > ---
> > Added in v3
> > 
> >  lib/vsprintf.c | 18 +++++++++++++++---
> >  1 file changed, 15 insertions(+), 3 deletions(-)  
> 
> The diffstat here, or for some other patch in the same series,
> definitely ought to mention lib/test_printf.c.
> 
> > diff --git a/lib/vsprintf.c b/lib/vsprintf.c
> > index be71a03c936a..8aee1caabd9e 100644
> > --- a/lib/vsprintf.c
> > +++ b/lib/vsprintf.c
> > @@ -1269,9 +1269,10 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
> >  {
> >  	char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
> >  	char *p = mac_addr;
> > -	int i;
> > +	int i, pos;
> >  	char separator;
> >  	bool reversed = false;
> > +	bool uppercase = false;
> >  
> >  	if (check_pointer(&buf, end, addr, spec))
> >  		return buf;
> > @@ -1281,6 +1282,10 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
> >  		separator = '-';
> >  		break;
> >  
> > +	case 'U':
> > +		uppercase = true;
> > +		break;
> > +
> >  	case 'R':
> >  		reversed = true;
> >  		fallthrough;  
> 
> This seems broken, and I'm surprised the compiler doesn't warn about
> separator possibly being uninitialized further down. I'm also surprised
> your testing hasn't caught this. For reference, the full switch
> statement is currently

Compiler (gcc) does not warn because of Makefile:

  1038 # Enabled with W=2, disabled by default as noisy
  1039 ifdef CONFIG_CC_IS_GCC
  1040 KBUILD_CFLAGS += -Wno-maybe-uninitialized
  1041 endif

With this commented:

  lib/vsprintf.c: In function ‘mac_address_string’:
  lib/vsprintf.c:1310:30: warning: ‘separator’ may be used uninitialized [-Wmaybe-uninitialized]
   1310 |                         *p++ = separator;
        |                         ~~~~~^~~~~~~~~~~
  lib/vsprintf.c:1273:14: note: ‘separator’ was declared here
   1273 |         char separator;
        |              ^~~~~~~~~

Regards,
Peter

> 
>         switch (fmt[1]) {
>         case 'F':
>                 separator = '-';
>                 break;
> 
>         case 'R':
>                 reversed = true;
>                 fallthrough;
> 
>         default:
>                 separator = ':';
>                 break;
>         }
> 
> > @@ -1292,9 +1297,14 @@ char *mac_address_string(char *buf, char *end, u8 *addr,
> >  
> >  	for (i = 0; i < 6; i++) {
> >  		if (reversed)
> > -			p = hex_byte_pack(p, addr[5 - i]);
> > +			pos = 5 - i;
> > +		else
> > +			pos = i;
> > +
> > +		if (uppercase)
> > +			p = hex_byte_pack_upper(p, addr[pos]);
> >  		else
> > -			p = hex_byte_pack(p, addr[i]);
> > +			p = hex_byte_pack(p, addr[pos]);  
> 
> I think this becomes quite hard to follow. We have string_upper() in
> linux/string_helpers.h, so I'd rather just leave this loop alone and do
> 
>   if (uppercase)
>     string_upper(mac_addr, mac_addr);
> 
> after the nul-termination.
> 
> Rasmus
>
Rasmus Villemoes April 28, 2023, 6:56 a.m. UTC | #5
On 27/04/2023 13.51, Konrad Gräfe wrote:
> The CDC-ECM specification requires an USB gadget to send the host MAC
> address as uppercase hex string. This change adds the appropriate
> modifier.

Thinking more about it, I'm not sure this is appropriate, not for a
single user like this. vsprintf() should not and cannot satisfy all
possible string formatting requirements for the whole kernel. The %pX
extensions are convenient for use with printk() and friends where one
needs what in other languages would be "string interpolation" (because
then the caller doesn't need to deal with temporary stack buffers and
pass them as %s arguments), but for single items like this, snprintf()
is not necessarily the right tool for the job.

In this case, the caller can just as well call string_upper() on the
result, or not use sprintf() at all and do a tiny loop with
hex_byte_pack_upper().

Rasmus
Greg KH April 28, 2023, 7:19 a.m. UTC | #6
On Fri, Apr 28, 2023 at 08:56:59AM +0200, Rasmus Villemoes wrote:
> On 27/04/2023 13.51, Konrad Gräfe wrote:
> > The CDC-ECM specification requires an USB gadget to send the host MAC
> > address as uppercase hex string. This change adds the appropriate
> > modifier.
> 
> Thinking more about it, I'm not sure this is appropriate, not for a
> single user like this. vsprintf() should not and cannot satisfy all
> possible string formatting requirements for the whole kernel. The %pX
> extensions are convenient for use with printk() and friends where one
> needs what in other languages would be "string interpolation" (because
> then the caller doesn't need to deal with temporary stack buffers and
> pass them as %s arguments), but for single items like this, snprintf()
> is not necessarily the right tool for the job.

But sprintf() already creates mac address strings today, adding
yet-another-modifier makes it so that we don't have to hand-roll this
type of logic in the individual drivers that require it.

thanks,

greg k-h
David Laight April 28, 2023, 7:46 a.m. UTC | #7
From: Rasmus Villemoes
> Sent: 28 April 2023 07:57
> 
> On 27/04/2023 13.51, Konrad Gräfe wrote:
> > The CDC-ECM specification requires an USB gadget to send the host MAC
> > address as uppercase hex string. This change adds the appropriate
> > modifier.
> 
> Thinking more about it, I'm not sure this is appropriate, not for a
> single user like this. vsprintf() should not and cannot satisfy all
> possible string formatting requirements for the whole kernel. The %pX
> extensions are convenient for use with printk() and friends where one
> needs what in other languages would be "string interpolation" (because
> then the caller doesn't need to deal with temporary stack buffers and
> pass them as %s arguments), but for single items like this, snprintf()
> is not necessarily the right tool for the job.
> 
> In this case, the caller can just as well call string_upper() on the
> result, or not use sprintf() at all and do a tiny loop with
> hex_byte_pack_upper().

Or snprintf with "%02X:%02X:%02X:%02X:%02X:%02X".

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
Petr Mladek May 2, 2023, 12:23 p.m. UTC | #8
On Fri 2023-04-28 08:56:59, Rasmus Villemoes wrote:
> On 27/04/2023 13.51, Konrad Gräfe wrote:
> > The CDC-ECM specification requires an USB gadget to send the host MAC
> > address as uppercase hex string. This change adds the appropriate
> > modifier.
> 
> Thinking more about it, I'm not sure this is appropriate, not for a
> single user like this. vsprintf() should not and cannot satisfy all
> possible string formatting requirements for the whole kernel. The %pX
> extensions are convenient for use with printk() and friends where one
> needs what in other languages would be "string interpolation" (because
> then the caller doesn't need to deal with temporary stack buffers and
> pass them as %s arguments), but for single items like this, snprintf()
> is not necessarily the right tool for the job.
>
> In this case, the caller can just as well call string_upper() on the
> result

I tend to agree with Rasmus. string_upper() is a super-easy solution.
One user does not look worth adding all the churn into vsprintf().

Best Regards,
Petr
Andy Shevchenko May 2, 2023, 8:01 p.m. UTC | #9
On Fri, Apr 28, 2023 at 07:46:14AM +0000, David Laight wrote:
> From: Rasmus Villemoes
> > Sent: 28 April 2023 07:57
> > On 27/04/2023 13.51, Konrad Gräfe wrote:
> > > The CDC-ECM specification requires an USB gadget to send the host MAC
> > > address as uppercase hex string. This change adds the appropriate
> > > modifier.
> > 
> > Thinking more about it, I'm not sure this is appropriate, not for a
> > single user like this. vsprintf() should not and cannot satisfy all
> > possible string formatting requirements for the whole kernel. The %pX
> > extensions are convenient for use with printk() and friends where one
> > needs what in other languages would be "string interpolation" (because
> > then the caller doesn't need to deal with temporary stack buffers and
> > pass them as %s arguments), but for single items like this, snprintf()
> > is not necessarily the right tool for the job.
> > 
> > In this case, the caller can just as well call string_upper() on the
> > result, or not use sprintf() at all and do a tiny loop with
> > hex_byte_pack_upper().
> 
> Or snprintf with "%02X:%02X:%02X:%02X:%02X:%02X".

Of course this is a step back. Why? Have you read actually what we have in %p
extensions already?

Also, what about stack?

Entire %pm/M exists due to reversed order. Otherwise it's an alias to %6phD or
alike.
Konrad Gräfe May 4, 2023, 1:25 p.m. UTC | #10
On 02.05.23 14:23, Petr Mladek wrote:
> On Fri 2023-04-28 08:56:59, Rasmus Villemoes wrote:
>> On 27/04/2023 13.51, Konrad Gräfe wrote:
>>> The CDC-ECM specification requires an USB gadget to send the host MAC
>>> address as uppercase hex string. This change adds the appropriate
>>> modifier.
>>
>> Thinking more about it, I'm not sure this is appropriate, not for a
>> single user like this. vsprintf() should not and cannot satisfy all
>> possible string formatting requirements for the whole kernel. The %pX
>> extensions are convenient for use with printk() and friends where one
>> needs what in other languages would be "string interpolation" (because
>> then the caller doesn't need to deal with temporary stack buffers and
>> pass them as %s arguments), but for single items like this, snprintf()
>> is not necessarily the right tool for the job.
>>
>> In this case, the caller can just as well call string_upper() on the
>> result
> 
> I tend to agree with Rasmus. string_upper() is a super-easy solution.
> One user does not look worth adding all the churn into vsprintf().
> 
> Best Regards,
> Petr

I do agree as well. That would basically be v1 [1] without the 
hand-crafted string_upper(). (I didn't know the function.)

Regards,
Konrad

[1]: 
https://lore.kernel.org/linux-usb/94afd6e0-7300-e8f4-d52e-c21acec04f5b@gateware.de/
diff mbox series

Patch

diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index be71a03c936a..8aee1caabd9e 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -1269,9 +1269,10 @@  char *mac_address_string(char *buf, char *end, u8 *addr,
 {
 	char mac_addr[sizeof("xx:xx:xx:xx:xx:xx")];
 	char *p = mac_addr;
-	int i;
+	int i, pos;
 	char separator;
 	bool reversed = false;
+	bool uppercase = false;
 
 	if (check_pointer(&buf, end, addr, spec))
 		return buf;
@@ -1281,6 +1282,10 @@  char *mac_address_string(char *buf, char *end, u8 *addr,
 		separator = '-';
 		break;
 
+	case 'U':
+		uppercase = true;
+		break;
+
 	case 'R':
 		reversed = true;
 		fallthrough;
@@ -1292,9 +1297,14 @@  char *mac_address_string(char *buf, char *end, u8 *addr,
 
 	for (i = 0; i < 6; i++) {
 		if (reversed)
-			p = hex_byte_pack(p, addr[5 - i]);
+			pos = 5 - i;
+		else
+			pos = i;
+
+		if (uppercase)
+			p = hex_byte_pack_upper(p, addr[pos]);
 		else
-			p = hex_byte_pack(p, addr[i]);
+			p = hex_byte_pack(p, addr[pos]);
 
 		if (fmt[0] == 'M' && i != 5)
 			*p++ = separator;
@@ -2279,6 +2289,7 @@  char *rust_fmt_argument(char *buf, char *end, void *ptr);
  * - 'm' For a 6-byte MAC address, it prints the hex address without colons
  * - 'MF' For a 6-byte MAC FDDI address, it prints the address
  *       with a dash-separated hex notation
+ * - '[mM]U' For a 6-byte MAC address in uppercase hex
  * - '[mM]R' For a 6-byte MAC address, Reverse order (Bluetooth)
  * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
  *       IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
@@ -2407,6 +2418,7 @@  char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 	case 'M':			/* Colon separated: 00:01:02:03:04:05 */
 	case 'm':			/* Contiguous: 000102030405 */
 					/* [mM]F (FDDI) */
+					/* [mM]U (Uppercase hex) */
 					/* [mM]R (Reverse order; Bluetooth) */
 		return mac_address_string(buf, end, ptr, spec, fmt);
 	case 'I':			/* Formatted IP supported