Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/uu/dd/src/dd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,10 @@ impl Num {

fn to_bytes(self, block_size: u64) -> u64 {
match self {
Self::Blocks(n) => n * block_size,
// Saturate on overflow: a byte count above `u64::MAX` is far beyond
// the `i64::MAX` (intmax_t) limit that callers enforce, so clamping
// here turns a would-be panic into that clean "too large" error.
Self::Blocks(n) => n.saturating_mul(block_size),
Self::Bytes(n) => n,
}
}
Expand Down
10 changes: 10 additions & 0 deletions src/uu/dd/src/parseargs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,16 @@ impl Parser {
}

let count = self.count.map(|c| c.force_bytes_if(self.iflag.count_bytes));
// GNU coreutils has a limit of i64 (intmax_t)
if let Some(count) = count {
let count_bytes = count.to_bytes(ibs as u64);
if count_bytes > i64::MAX as u64 {
return Err(ParseError::InvalidNumberWithErrMsg(
format!("{count_bytes}"),
"Value too large for defined data type".to_string(),
));
}
}

Ok(Settings {
skip,
Expand Down
20 changes: 20 additions & 0 deletions tests/by-util/test_dd.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,26 @@ fn test_out_of_memory_skip() {
.stderr_contains("memory");
}

#[test]
fn test_large_numeric_operands_do_not_panic() {
// Regression test for GH #12843, #12845, #12846, #12848: a huge
// count/skip/seek/iseek/oseek operand overflowed an internal multiplication
// and panicked instead of reporting a clean "too large" error.
for operand in [
"count=177817277272177278",
"skip=99999999999999999999",
"seek=99999999999999999999",
"iseek=166727721627616621762772",
"oseek=166727721627616621762772",
] {
new_ucmd!()
.arg(operand)
.pipe_in("")
.fails_with_code(1)
.stderr_contains("Value too large for defined data type");
}
}

#[test]
fn test_stdin_stdout() {
let input = build_ascii_block(521);
Expand Down
Loading