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]