]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
vsprintf: don't make the 'binary' version pack small integer arguments
authorLinus Torvalds <torvalds@linux-foundation.org>
Mon, 23 Dec 2024 19:34:32 +0000 (11:34 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Mon, 23 Dec 2024 19:52:34 +0000 (11:52 -0800)
The strange vbin_printf / bstr_printf interface used to save one- and
two-byte printf numerical arguments into their packed format.

That's more than a bit strange since the argument buffer is supposed to
be an array of 'u32' words, and it's also very different from how the
source of the data (varargs) work - which always do the normal integer
type conversions, so 'char' and 'short' are always passed as int-sized
anyway.

This odd packing causes extra code complexity, and it really isn't worth
it, since the space savings are simply not there: it only happens for
formats like '%hd' (short) and '%hhd' (char), which are very rare
indeed.

In fact, the only other user of this interface seems to be the bpf
helper code (bpf_bprintf_prepare()), and Alexei points out that that
case doesn't support those truncated integer formatting options at all
in the first place.

As a result, bpf_bprintf_prepare() doesn't need any changes for this,
and TRACE_BPRINT uses 'vbin_printf()' -> 'bstr_printf()' for the
formatting and hopefully doesn't expose the odd packing any other way
(knock wood).

Link: https://lore.kernel.org/all/CAADnVQJy65oOubjxM-378O3wDfhuwg8TGa9hc-cTv6NmmUSykQ@mail.gmail.com/
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
lib/vsprintf.c

index 7a40c8ae2d190d0c25fe39f3644eb6bc4aefb414..a49bb6eb24350ffbabe106e0c4d7373e7fa4c9cd 100644 (file)
@@ -3137,17 +3137,9 @@ int vbin_printf(u32 *bin_buf, size_t size, const char *fmt_str, va_list args)
                        break;
 
                case FORMAT_STATE_NUM:
-                       switch (fmt.size) {
-                       case 8:
+                       if (fmt.size > sizeof(int)) {
                                save_arg(long long);
-                               break;
-                       case 1:
-                               save_arg(char);
-                               break;
-                       case 2:
-                               save_arg(short);
-                               break;
-                       default:
+                       } else {
                                save_arg(int);
                        }
                }
@@ -3318,23 +3310,14 @@ int bstr_printf(char *buf, size_t size, const char *fmt_str, const u32 *bin_buf)
                        goto out;
 
                case FORMAT_STATE_NUM:
-                       switch (fmt.size) {
-                       case 8:
+                       if (fmt.size > sizeof(int)) {
                                num = get_arg(long long);
-                               break;
-                       case 1:
-                               num = convert_num_spec(get_arg(char), fmt.size, spec);
-                               break;
-                       case 2:
-                               num = convert_num_spec(get_arg(short), fmt.size, spec);
-                               break;
-                       default:
+                       } else {
                                num = convert_num_spec(get_arg(int), fmt.size, spec);
-                               break;
                        }
+                       str = number(str, end, num, spec);
+                       continue;
                }
-
-               str = number(str, end, num, spec);
        } /* while(*fmt.str) */
 
 out: