Skip to content

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

Open
oliver-kopcik wants to merge 1 commit 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 1 commit into
uutils:mainfrom
oliver-kopcik:fix/dd-zero-factor-short-circuit

Conversation

@oliver-kopcik

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

Note that this does not make GNU's tests/dd/misc.sh pass on its own; as #14160 says, that test then reaches a second, separate difference (failed to seek in output file: Illegal seek).

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

Copy link
Copy Markdown

GNU testsuite comparison:

Skipping an intermittent issue tests/date/date-locale-hour (passes in this run but fails in the 'main' branch)
Congrats! The gnu test tests/dd/misc is no longer failing!
Skip an intermittent issue tests/pr/bounded-memory (was skipped on 'main', 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