Skip to content

Commit 79824f7

Browse files
Copilotjgarzik
andcommitted
Improve validation logic and add size limit test
- Make argument size validation more idiomatic using iterator methods - Add explicit test for -I mode 4096 byte limit enforcement - All 25 xargs tests passing (up from 17 originally) Co-authored-by: jgarzik <494411+jgarzik@users.noreply.github.com>
1 parent e07ad5b commit 79824f7

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

process/tests/xargs/mod.rs

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
// SPDX-License-Identifier: MIT
88
//
99

10-
use plib::testing::{run_test, TestPlan};
10+
use plib::testing::{run_test, run_test_with_checker, TestPlan};
1111

1212
fn xargs_test(test_data: &str, expected_output: &str, args: Vec<&str>) {
1313
run_test(TestPlan {
@@ -312,3 +312,40 @@ fn xargs_combine_n_and_s() {
312312
expected_exit_code: 0,
313313
});
314314
}
315+
316+
#[test]
317+
fn xargs_insert_arg_size_limit() {
318+
// -I mode should enforce size limit on constructed arguments
319+
// Create a string that when repeated will exceed 4096 bytes
320+
let long_input = "x".repeat(5000);
321+
let test_plan = TestPlan {
322+
cmd: String::from("xargs"),
323+
args: vec![
324+
"-I".to_string(),
325+
"{}".to_string(),
326+
"echo".to_string(),
327+
"{}".to_string(),
328+
],
329+
stdin_data: format!("{}\n", long_input),
330+
expected_out: String::from(""),
331+
expected_err: String::from(""),
332+
expected_exit_code: 1,
333+
};
334+
335+
// Run with custom checker since error format includes Rust error wrapper
336+
run_test_with_checker(test_plan, |plan, output| {
337+
assert_eq!(output.status.code(), Some(plan.expected_exit_code));
338+
assert_eq!(String::from_utf8_lossy(&output.stdout), plan.expected_out);
339+
// Just verify stderr contains the key message parts
340+
let stderr = String::from_utf8_lossy(&output.stderr);
341+
assert!(
342+
stderr.contains("constructed argument"),
343+
"Expected error about constructed argument"
344+
);
345+
assert!(stderr.contains("5000 bytes"), "Expected size in error");
346+
assert!(
347+
stderr.contains("4096 byte limit"),
348+
"Expected limit in error"
349+
);
350+
});
351+
}

process/xargs.rs

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -541,16 +541,15 @@ fn exec_insert_mode(
541541

542542
// POSIX: Check that constructed arguments don't exceed the limit
543543
// POSIX requires at least 255 bytes, we use INSERT_ARG_MAX (4096)
544-
for arg in &util_args {
545-
if arg.len() > INSERT_ARG_MAX {
546-
return Err(io::Error::new(
547-
io::ErrorKind::InvalidInput,
548-
format!(
549-
"xargs: constructed argument exceeds {} byte limit in insert mode",
550-
INSERT_ARG_MAX
551-
),
552-
));
553-
}
544+
if let Some(arg) = util_args.iter().find(|arg| arg.len() > INSERT_ARG_MAX) {
545+
return Err(io::Error::new(
546+
io::ErrorKind::InvalidInput,
547+
format!(
548+
"xargs: constructed argument of {} bytes exceeds {} byte limit in insert mode",
549+
arg.len(),
550+
INSERT_ARG_MAX
551+
),
552+
));
554553
}
555554

556555
exec_util(&args.util, util_args, trace, prompt)

0 commit comments

Comments
 (0)