casaroli opened a new pull request, #21595:
URL: https://github.com/apache/nuttx/pull/21595

   Part of #21467.
   
   ## Summary
   
   Since #21474, `printf()` takes the pointer of `%n`, stores nothing and 
prints `?` when `LIBC_PRINTF_PERCENT_N` is off. But the correct output of `%n` 
is empty: the `?` changes the text and the return value of the call. The safety 
comes from the missing store, not from the `?`.
   
   Now `%n` prints nothing also with the option off. It still reads its pointer 
and stores nothing, so a format still cannot write to memory. With the option 
on, nothing changes: `%n` stores the count and prints nothing.
   
   ```
   printf("ab%n|%s", &n, "str")   before: "ab?|str", returns 7   now: "ab|str", 
returns 6
   ```
   
   A width or flags on `%n` have no effect, as C leaves them undefined.
   
   Two commits: the code and the help of `LIBC_PRINTF_PERCENT_N`, then the page 
`Documentation/os/libs/libc/printf.rst`.
   
   ## Impact
   
   A program sees one change: with `LIBC_PRINTF_PERCENT_N` off (the default in 
all profiles), `%n` printed `?` and now prints nothing, so the text and the 
return value of the call change. With the option on, nothing changes. No other 
output changes. No new option. No ABI change. No architecture code. Flat, 
protected and kernel builds.
   
   No program in nuttx or nuttx-apps prints with `%n`, except `printftest`. Its 
update is in apache/nuttx-apps#3994.
   
   Size (`text` of the image, and `lib_libvsprintf.o`, in bytes; the stack 
frame of `vsprintf_internal()` does not change):
   
   | build | master | this PR | change |
   |---|---|---|---|
   | `nucleo-f072rb:nsh` (Cortex-M0), Default | 46,792 | 46,804 | +12 |
   | `nucleo-f072rb:nsh`, Minimal | 46,460 | 46,464 | +4 |
   | `nucleo-f072rb:nsh`, Full | 58,072 | 58,064 | -8 |
   | `qemu-armv8a:nsh` (arm64), Default | 329,608 | 329,612 | +4 |
   | `lib_libvsprintf.o`, Cortex-M0, Default | 1,599 | 1,611 | +12 |
   
   The `?` path of `%n` is gone, so the code is shorter. On Cortex-M0 GCC then 
puts the blocks of `vsprintf_internal()` in another order, and three short 
conditional branches need one more jump each: +12 bytes in Default. In Full it 
is 8 bytes smaller.
   
   ## Testing
   
   With apache/nuttx-apps#3994 (`printftest`, `printfengine`), under QEMU with 
HVF, then ostest; each run passes and ostest exits with status 0:
   
   | build | printf settings |
   |---|---|
   | `qemu-armv8a:knsh` (kernel) | Default |
   | `qemu-armv8a:knsh` | Full |
   | `qemu-armv8a:knsh` | Minimal |
   | `qemu-armv8a:knsh` | Default, `LIBC_PRINTF_OCTAL=n`, 
`LIBC_PRINTF_LEFT_JUSTIFY=n` |
   | `qemu-armv8a:knsh` | Full, `LIBC_PRINTF_PERCENT_N=y` |
   | `qemu-armv8a:knsh` | Minimal, `LIBC_PRINTF_PERCENT_N=y`, 
`LIBC_PRINTF_OCTAL=n`, `LIBC_PRINTF_LEFT_JUSTIFY=n` |
   | `qemu-armv8a:nsh` (flat) | Default |
   | `qemu-armv8a:nsh` | Full, `LIBC_PRINTF_PERCENT_N=y` |
   
   Full has `LIBC_NUMBERED_ARGS` on, so `%2$s%1$n` runs too. `printfengine` 
needs floating point, so it does not run with Minimal. The test checks the text 
and the return value, for example `snprintf(NULL, 0, "ab%n|%s", &n, "str")` 
returns 6, and checks the store only with the option on.
   
   On master the same test fails with the option off, as it must: `"ab%n|%s" 
returned 7: "ab?|str", expected "ab|str"` (`qemu-armv8a:knsh`, Default). With 
the option on it passes on master too.
   
   The examples of `%n` on the page come from a run of the examples of the page 
on `rv-virt:nsh` (rv32, QEMU) with Full, Full with `LIBC_PRINTF_PERCENT_N=y`, 
Default, Minimal and Minimal with all options off. The page made from these 
runs is the same as the page in this PR. With the option on, the example stores 
2 in `n`; in all other runs it stores nothing.
   
   Builds with `-Werror`: `qemu-armv8a:nsh` (Default; Full with 
`LIBC_PRINTF_PERCENT_N=y`), `qemu-armv8a:knsh` (the same two), `rv-virt:nsh64` 
(the same two), `nucleo-f072rb:nsh` (Full with `LIBC_PRINTF_PERCENT_N=y`; 
Default, Minimal and Full for the size). `qemu-intel64:nsh` (GCC 16.2, Default, 
both test programs on) builds, but not with `-Werror`: its only warning is in 
`libs/libm/libm/lib_gamma.c` (`sinpi` shadows a built-in function), on master 
too.
   
   The documentation build with `-W` gives one warning, for another page: 
`plantuml` is not installed on the build host 
(`guides/porting/port_bootsequence.rst`). There is no warning for `printf.rst`.
   
   `tools/checkpatch.sh -c -u -m -g` passes.
   
   Not run: a CMake build, a protected build, hardware, the suite at 
https://github.com/casaroli/printf-report.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to