printf: a malformed \u or \U in a %b argument drops characters and exits 0
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 24.1k
- Forks
- 2k
- Avg merge
- 1d 5h
- Merged PRs (30d)
- 365
Description
printf '%b' doesn't reject a malformed \x, \u or \U in its argument the way the format string does, and for \u and \U it also loses the characters it consumed.
$ printf '%b\n' 'C:\users\file'
C:\x^Lile
$ echo $?
0
sers is gone. The \u consumed the four characters after it, failed to parse them as hex, wrote a literal \x — the input said \u — and dropped them. The \f in \file then produced the form feed. Nothing on stderr, exit status 0.
GNU 9.7 stops at the bad escape:
$ printf '%b\n' 'C:\users\file'
printf: missing hexadecimal number in escape
$ echo $?
1
The same escapes are already handled in the format string — it is only the %b argument path:
| escape | in the format string | as a %b argument |
|---|---|---|
\x |
exit 1, missing hexadecimal number in escape |
prints \x, exit 0 |
\u |
exit 1, same message | prints \x, exit 0 |
\U41 |
exit 1, same message | prints \x41, exit 0 |
\uD800 |
exit 1, invalid universal character name \uD800 |
prints \x, exit 0 |
GNU exits 1 in all eight cells.
How much text disappears follows the escape form — four characters for \u, eight for \U — and nothing disappears when fewer than that remain:
$ printf '%b' '\uABCZ|TAIL' -> \x|TAIL
$ printf '%b' '\U0000004Z|TAIL' -> \x|TAIL
$ printf '%b' 'x\unit' -> x\xnit (only three characters left)
Well-formed escapes are unaffected: \u0041Z, \U00000041Z and \x41Z all give AZ in both implementations.
The \x part of this looks like the tail of #7259, which taught the format string to error on a missing hex value in February 2025; the %b argument path wasn't included.
uutils 0.11.0 built from main, GNU coreutils 9.7 on Ubuntu 26.04, LC_ALL=C.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
The payload names no source file or test; start by reproducing the %b cases under LC_ALL=C and compare that path with the format-string handling described in issue #7259. Done means malformed \x, \u, and \U report errors, preserve consumed characters, and exit 1, while valid escapes remain unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 70/100