mirror of
https://github.com/uutils/coreutils.git
synced 2026-10-28 10:45:25 +08:00
printf: reject a * precision above INT_MAX for %s
The %s arm resolved a `*` precision without the check_precision call the integer and float arms make, so a value above i32::MAX was used as is instead of failing with "invalid precision". Check it there, for a `*` precision only; a precision written in the format is still accepted. Closes #15663
This commit is contained in:
1 parent
c21b7adc66
commit
3017dccfaf
2 files changed
+34
No files matched your search
@@ -369,7 +369,13 @@ impl Spec {
|
||||
// For now, we let printf panic when we truncate within a code point.
|
||||
// TODO: We need to not use Rust's formatting for aligning the output,
|
||||
// so that we can just write bytes to stdout without panicking.
|
||||
let star_precision = matches!(precision, Some(CanAsterisk::Asterisk(_)));
|
||||
let precision = resolve_asterisk_precision(*precision, args);
|
||||
// A `*` precision is an int argument, so it is capped at i32::MAX like
|
||||
// the numeric specs; a precision written in the format is not.
|
||||
if star_precision && let Some(precision) = precision {
|
||||
check_precision(precision)?;
|
||||
}
|
||||
let os_str = args.next_string(*position);
|
||||
let bytes = os_str_as_bytes(os_str)?;
|
||||
|
||||
|
||||
@@ -666,6 +666,34 @@ fn invalid_precision_tests() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_star_precision_string() {
|
||||
for precision in ["2147483648", &i64::MAX.to_string()] {
|
||||
new_ucmd!()
|
||||
.args(&["%.*s|\n", precision, "x"])
|
||||
.fails_with_code(1)
|
||||
.no_stdout()
|
||||
.stderr_is(format!("printf: invalid precision: '{precision}'\n"));
|
||||
}
|
||||
|
||||
// The failure ends printf, so the rest of the format is not run.
|
||||
new_ucmd!()
|
||||
.args(&["%.*s %s\n", "2147483648", "a", "b"])
|
||||
.fails_with_code(1)
|
||||
.no_stdout()
|
||||
.stderr_is("printf: invalid precision: '2147483648'\n");
|
||||
|
||||
// The cap is i32::MAX itself, and only a `*` precision is capped.
|
||||
new_ucmd!()
|
||||
.args(&["%.*s|\n", "2147483647", "x"])
|
||||
.succeeds()
|
||||
.stdout_only("x|\n");
|
||||
new_ucmd!()
|
||||
.args(&["%.4294967296s|\n", "x"])
|
||||
.succeeds()
|
||||
.stdout_only("x|\n");
|
||||
}
|
||||
|
||||
// The following padding-tests test for the cases in which flags in ['0', ' '] are given.
|
||||
// For integer, only try to pad when no precision is given, while
|
||||
// for float, always try to pad
|
||||
|
||||
Reference in new issue
Block a user