casaroli opened a new issue, #21467:
URL: https://github.com/apache/nuttx/issues/21467

   ## Summary
   
   `printf` in NuttX can hang, can read outside a buffer, and gives wrong 
output for valid formats. I want to fix this in small steps, with a test suite 
to measure each step, and without growth on small boards. This issue holds the 
plan and links the PRs. Comments on the plan are welcome before the larger 
steps.
   
   ## The measurement
   
   The suite is https://github.com/casaroli/printf-report: 45,084 tests, each 
tagged with the document that requires the behaviour (C99, C23, POSIX), and 
expected results that come from a model of the standard text, not from another 
C library. The published run of NuttX 13.1 on sim, with `LIBC_FLOATINGPOINT`, 
`LIBC_NUMBERED_ARGS` and `LIBC_LOCALE`:
   
   | Measure | Result |
   |---|---|
   | C99 required | 61.70% |
   | Correctly rounded | 57.28% |
   | C23 | 1.08% |
   | POSIX | 65.85% |
   | XSI | 36.36% |
   | Tests that crash or hang | 42 |
   
   Findings from that report, each reproduced with a standalone program. Some 
code has changed since, so the first step runs the suite again on current 
master:
   
   - It hangs on integer widths of 256 or more, and on `%.Ne` with a precision 
of 255 or more.
   - `%#.0x` of 0 reads `buf[-1]`.
   - `%.0g` writes a NUL byte.
   - `%n` is printed as text, and the arguments after it are then misread.
   - `%Lf` reads a `long double` as a `double`.
   - `-0.0` loses its sign.
   - There is no `%a`, and output has only 15 significant digits.
   
   ## Rules
   
   1. `printf` never crashes or hangs, in any configuration.
   2. A configuration has at least what it has today. The default stays as it 
is: floating point with `!DEFAULT_SMALL && ARCH_FPU`.
   3. The default configuration does not grow in flash. Each PR shows flash and 
stack, and any growth has a reason.
   
   A wrong argument is outside rule 1: `printf` cannot detect a bad pointer for 
`%s` or an argument of the wrong type. The documentation will say so.
   
   ## Design
   
   The parser is not optional. A crash comes from a format that is misread, not 
from a missing feature.
   
   - Always on: the full format grammar, and each argument read at its right 
size.
   - A conversion that is disabled still reads its argument, then prints `?` 
padded to the width, so the rest of the line stays correct.
   - An unknown conversion has no known size, so the rest of the format is 
printed as text and no more arguments are read.
   
   The features are options, and a profile (Minimal, Default, Full) only sets 
their defaults. `LIBC_FLOATINGPOINT` and `LIBC_NUMBERED_ARGS` keep their names.
   
   | Option | Note |
   |---|---|
   | 64-bit integers on 32-bit CPUs | Can pull in libgcc division |
   | Floating point: none, as today, exact | Exact rounding costs stack and 
flash |
   | `%a` | Separate from exact rounding |
   | `long double` | Only where it differs from `double` |
   | Wide characters | |
   | Positional arguments | `LIBC_NUMBERED_ARGS` |
   | Locale and `'` grouping | |
   | `%n` | Off by default: it reads its pointer and stores nothing |
   | C23 `%b` and `%wN` | |
   
   The sizes are not measured yet, so this list can change.
   
   ## Steps
   
   One topic in each PR:
   
   - [ ] Safety: no crash and no hang, no new options
   - [ ] Options and profiles: the existing features behind options, with no 
change in the default
   - [ ] Argument sizes: `%n`, `%L`, unknown conversions
   - [ ] Output: `-0.0`, then `%a` and C23, each behind its option
   - [ ] Exact floating point behind its option, after a discussion here
   
   A new feature comes in off in the Default profile, so it does not grow the 
default configuration.
   
   Tests: the suite on each profile with 0 crashes and hangs, a fuzz run on the 
host under ASan and UBSan, and a test in nuttx-apps where CI can run it.
   
   ## Alternatives
   
   - One large PR: hard to review, and it conflicts with other work in the file.
   - All of it always on: it grows the small boards.
   - A new library for `printf`: more risk than a fix, and the small boards 
still need a small path.
   
   ## Related
   
   #21340 refactors the same file. The order of that PR and these steps is for 
its author and me to agree.
   


-- 
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