uutils / uutils/coreutils

printf: a malformed \u or \U in a %b argument drops characters and exits 0

Open
#14,404 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.