Skip to content

dd: stop at a zero factor in a multiplier expression - #14299

Open
oliver-kopcik wants to merge 2 commits into
uutils:mainfrom
oliver-kopcik:fix/dd-zero-factor-short-circuit
Open

dd: stop at a zero factor in a multiplier expression#14299
oliver-kopcik wants to merge 2 commits into
uutils:mainfrom
oliver-kopcik:fix/dd-zero-factor-short-circuit

Conversation

@oliver-kopcik

@oliver-kopcik oliver-kopcik commented Aug 31, 2026

Copy link
Copy Markdown

Fixes #14160.

The bug

A zero factor makes a whole multiplier expression zero, so the factors after it are never looked at. parse_bytes_with_opt_multiplier parsed every factor up front instead, so a later factor that does not fit in a u64 failed the whole argument:

$ dd count=00x9999999999999999999999999999999999999999999999999999999999999 </dev/null
dd: invalid number: '00x999…': Value too large for defined data type   # exit 1

It should copy zero blocks and exit successfully, which it did before 7f9b9a6 ("dd: reject a number that does not fit in u64") turned ParseSizeError::SizeTooBig into an error rather than u64::MAX. The zero factor case was not covered there.

After this change:

$ dd count=00x9999999999999999999999999999999999999999999999999999999999999 </dev/null
0+0 records in
0+0 records out
0 bytes copied, 0.0003494 s, 0.0 B/s                                   # exit 0

The change

Return as soon as a factor parses to zero, so the remaining factors are never parsed. A number that does not fit in a u64 on its own stays an error, so the behaviour 7f9b9a6 added is kept.

The zero-multiplier warning is only a check on the literal text and needs no parsing, so it moved into its own pass over the factors. That keeps it reported once per "0" factor — count=0x0x1 still warns twice, as test_zero_multiplier_warning requires. Folding it into the short-circuiting loop would have silently dropped the second warning.

Tests

Added a unit test in parseargs.rs and an end-to-end test in tests/by-util/test_dd.rs. Both fail on main and pass with the change — verified by reverting just the if num == 0 block and re-running:

test parseargs::tests::test_parse_bytes_with_opt_multiplier_zero_factor ... FAILED
test test_dd::test_zero_factor_skips_the_rest_of_the_multiplier ... FAILED

The unit test covers a zero factor leading, in the middle, and trailing, with and without an oversized factor after it.

Run locally on Windows (x86_64-pc-windows-msvc):

  • cargo test -p uu_dd --lib — 84 passed, 0 failed
  • cargo test --features dd --test tests -- test_dd — 111 passed, 0 failed
  • cargo fmt --all -- --check — clean
  • cargo clippy -p uu_dd --all-targets — no new warnings

On tests/dd/misc

#14160 expects this fix alone to leave GNU's tests/dd/misc still failing, on a second difference
(dd: failed to seek in output file: Illegal seek). That turns out not to hold — the GNU test job
on this PR reports:

Congrats! The gnu test tests/dd/misc is no longer failing!

So the whole test passes now, and the second difference either does not reproduce in CI or has been
resolved since the issue was filed. (An earlier version of this description repeated the issue's
expectation as though it still applied.)

A zero factor makes the whole multiplier expression zero, so the factors
after it are never looked at. We parsed every factor up front instead, so
a later one that does not fit in a u64 failed the whole argument:

    $ dd count=00x9999999999999999999999999999999999999999999999999999999999999
    dd: invalid number: '00x999…': Value too large for defined data type

That should copy zero blocks and exit successfully, which is what it did
before 7f9b9a6 ("dd: reject a number that does not fit in u64") turned
ParseSizeError::SizeTooBig into an error rather than u64::MAX. The zero
factor case was not covered there.

Return as soon as a factor parses to zero, so the rest is never parsed. A
number that does not fit in a u64 on its own stays an error.

The zero-multiplier warning is only a check on the literal text, so it is
kept in its own pass and still reported once per "0" factor.

Fixes uutils#14160

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Aug 31, 2026

Copy link
Copy Markdown

GNU testsuite comparison:

GNU test failed: tests/df/over-mount-device. tests/df/over-mount-device is passing on 'main'. Maybe you have to rebase?
Skip an intermittent issue tests/cut/bounded-memory (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/misc/tty-eof (fails in this run but passes in the 'main' branch)
Skip an intermittent issue tests/tail/symlink (fails in this run but passes in the 'main' branch)
Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Skipping an intermittent issue tests/tail/inotify-dir-recreate (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/cat/splice is no longer failing!
Congrats! The gnu test tests/cp/cp-a-selinux is no longer failing!
Congrats! The gnu test tests/cut/cut is no longer failing!
Congrats! The gnu test tests/cut/mb-non-utf8 is no longer failing!
Congrats! The gnu test tests/dd/partial-write is no longer failing!
Congrats! The gnu test tests/expand/mb is no longer failing!
Congrats! The gnu test tests/ls/stat-free-symlinks is no longer failing!
Congrats! The gnu test tests/misc/close-stdout is no longer failing!
Congrats! The gnu test tests/mktemp/write-error is no longer failing!
Congrats! The gnu test tests/mv/dir2dir is no longer failing!
Congrats! The gnu test tests/mv/mv-exchange is no longer failing!
Congrats! The gnu test tests/nl/multibyte is no longer failing!
Congrats! The gnu test tests/od/od-float is no longer failing!
Congrats! The gnu test tests/od/od-j is no longer failing!
Congrats! The gnu test tests/ptx/ptx-overrun is no longer failing!
Congrats! The gnu test tests/sort/sort-merge-fdlimit is no longer failing!
Congrats! The gnu test tests/unexpand/mb is no longer failing!
Note: The gnu test tests/dd/fail-ftruncate-fstat was skipped on 'main' but is now failing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dd: a zero factor no longer short-circuits the multiplier

1 participant