From 403ce6ea89c5264e697b284cc0c7ecdd9c3879c2 Mon Sep 17 00:00:00 2001 From: Kev1n8 <100595273+Kev1n8@users.noreply.github.com> Date: Sun, 30 Jun 2024 13:20:16 +0800 Subject: [PATCH 1/6] Add a new error type InvalidPrecision --- src/uucore/src/lib/features/format/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/uucore/src/lib/features/format/mod.rs b/src/uucore/src/lib/features/format/mod.rs index b82b5f62acf..500d5995b2c 100644 --- a/src/uucore/src/lib/features/format/mod.rs +++ b/src/uucore/src/lib/features/format/mod.rs @@ -62,6 +62,7 @@ pub enum FormatError { TooManySpecs(Vec), NeedAtLeastOneSpec(Vec), WrongSpecType, + InvalidPrecision(String), } impl Error for FormatError {} @@ -91,6 +92,11 @@ impl Display for FormatError { "format '{}' has no % directive", String::from_utf8_lossy(s) ), + Self::InvalidPrecision(precision) => write!( + f, + "invalid precision: '{}'", + precision + ), // TODO: Error message below needs some work Self::WrongSpecType => write!(f, "wrong % directive type was given"), Self::IoError(_) => write!(f, "io error"), From 193254d54e5801da4781cdcdec9b91c23de6607b Mon Sep 17 00:00:00 2001 From: Kev1n8 <100595273+Kev1n8@users.noreply.github.com> Date: Sun, 30 Jun 2024 13:21:25 +0800 Subject: [PATCH 2/6] check if the precision is valid before writing to stdout when it is signedInt, unsigned, or float --- src/uucore/src/lib/features/format/spec.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/uucore/src/lib/features/format/spec.rs b/src/uucore/src/lib/features/format/spec.rs index 543346bf43d..24f91769f37 100644 --- a/src/uucore/src/lib/features/format/spec.rs +++ b/src/uucore/src/lib/features/format/spec.rs @@ -374,6 +374,10 @@ impl Spec { let precision = resolve_asterisk(*precision, &mut args)?.unwrap_or(0); let i = args.get_i64(); + if precision > i32::MAX as usize { + return Err(FormatError::InvalidPrecision(precision.to_string())); + } + num_format::SignedInt { width, precision, @@ -393,6 +397,10 @@ impl Spec { let precision = resolve_asterisk(*precision, &mut args)?.unwrap_or(0); let i = args.get_u64(); + if precision > i32::MAX as usize { + return Err(FormatError::InvalidPrecision(precision.to_string())); + } + num_format::UnsignedInt { variant: *variant, precision, @@ -415,6 +423,10 @@ impl Spec { let precision = resolve_asterisk(*precision, &mut args)?.unwrap_or(6); let f = args.get_f64(); + if precision > i32::MAX as usize { + return Err(FormatError::InvalidPrecision(precision.to_string())); + } + num_format::Float { width, precision, From d646eeba038bb5ca5fa7f546b25caefe3399ffc3 Mon Sep 17 00:00:00 2001 From: Kev1n8 <100595273+Kev1n8@users.noreply.github.com> Date: Sun, 30 Jun 2024 13:22:15 +0800 Subject: [PATCH 3/6] add tests for invalid precision check --- tests/by-util/test_printf.rs | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index 7bf1fcfe5bf..85687280ec0 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -774,3 +774,21 @@ fn format_spec_zero_string_fails() { // It is invalid to have the format spec '%0s' new_ucmd!().args(&["%0s", "3"]).fails().code_is(1); } + +#[test] +fn invalid_precision_fails() { + // It is invalid to have length of output string greater than i32::MAX + new_ucmd!() + .args(&["%.*d", "2147483648", "0"]) + .fails() + .stderr_is("printf: invalid precision: '2147483648'\n"); +} + +#[test] +fn float_invalid_precision_fails() { + // It is invalid to have length of output string greater than i32::MAX + new_ucmd!() + .args(&["%.*f", "9999999999", "0"]) + .fails() + .stderr_is("printf: invalid precision: '9999999999'\n"); +} \ No newline at end of file From d203e76f2fa2744a24296e910f86066b48e13bc7 Mon Sep 17 00:00:00 2001 From: Kev1n8 <100595273+Kev1n8@users.noreply.github.com> Date: Sun, 30 Jun 2024 13:22:15 +0800 Subject: [PATCH 4/6] add tests for invalid precision check --- src/uucore/src/lib/features/format/mod.rs | 6 +----- tests/by-util/test_printf.rs | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/uucore/src/lib/features/format/mod.rs b/src/uucore/src/lib/features/format/mod.rs index 500d5995b2c..37db389802d 100644 --- a/src/uucore/src/lib/features/format/mod.rs +++ b/src/uucore/src/lib/features/format/mod.rs @@ -92,11 +92,7 @@ impl Display for FormatError { "format '{}' has no % directive", String::from_utf8_lossy(s) ), - Self::InvalidPrecision(precision) => write!( - f, - "invalid precision: '{}'", - precision - ), + Self::InvalidPrecision(precision) => write!(f, "invalid precision: '{}'", precision), // TODO: Error message below needs some work Self::WrongSpecType => write!(f, "wrong % directive type was given"), Self::IoError(_) => write!(f, "io error"), diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index 85687280ec0..4e72c69e56b 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -791,4 +791,4 @@ fn float_invalid_precision_fails() { .args(&["%.*f", "9999999999", "0"]) .fails() .stderr_is("printf: invalid precision: '9999999999'\n"); -} \ No newline at end of file +} From 7dd36d77c73d400f4a1f1c4f09aab4e8d0cf92da Mon Sep 17 00:00:00 2001 From: Kev1n8 <100595273+Kev1n8@users.noreply.github.com> Date: Sun, 30 Jun 2024 16:42:53 +0800 Subject: [PATCH 5/6] fix possible cross-platform issue that code failing to pass on some tests --- src/uucore/src/lib/features/format/spec.rs | 6 +++--- tests/by-util/test_printf.rs | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/uucore/src/lib/features/format/spec.rs b/src/uucore/src/lib/features/format/spec.rs index 24f91769f37..29e696d3235 100644 --- a/src/uucore/src/lib/features/format/spec.rs +++ b/src/uucore/src/lib/features/format/spec.rs @@ -374,7 +374,7 @@ impl Spec { let precision = resolve_asterisk(*precision, &mut args)?.unwrap_or(0); let i = args.get_i64(); - if precision > i32::MAX as usize { + if precision as u64 > i32::MAX as u64 { return Err(FormatError::InvalidPrecision(precision.to_string())); } @@ -397,7 +397,7 @@ impl Spec { let precision = resolve_asterisk(*precision, &mut args)?.unwrap_or(0); let i = args.get_u64(); - if precision > i32::MAX as usize { + if precision as u64 > i32::MAX as u64 { return Err(FormatError::InvalidPrecision(precision.to_string())); } @@ -423,7 +423,7 @@ impl Spec { let precision = resolve_asterisk(*precision, &mut args)?.unwrap_or(6); let f = args.get_f64(); - if precision > i32::MAX as usize { + if precision as u64 > i32::MAX as u64 { return Err(FormatError::InvalidPrecision(precision.to_string())); } diff --git a/tests/by-util/test_printf.rs b/tests/by-util/test_printf.rs index 4e72c69e56b..26f556e8e1d 100644 --- a/tests/by-util/test_printf.rs +++ b/tests/by-util/test_printf.rs @@ -788,7 +788,7 @@ fn invalid_precision_fails() { fn float_invalid_precision_fails() { // It is invalid to have length of output string greater than i32::MAX new_ucmd!() - .args(&["%.*f", "9999999999", "0"]) + .args(&["%.*f", "2147483648", "0"]) .fails() - .stderr_is("printf: invalid precision: '9999999999'\n"); + .stderr_is("printf: invalid precision: '2147483648'\n"); } From 4f477d933e157c1cbd8e46382abed9588abd50af Mon Sep 17 00:00:00 2001 From: Daniel Hofstetter Date: Mon, 1 Jul 2024 14:38:15 +0200 Subject: [PATCH 6/6] uucore/format: inline var in format string --- src/uucore/src/lib/features/format/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/uucore/src/lib/features/format/mod.rs b/src/uucore/src/lib/features/format/mod.rs index 37db389802d..6d7a2ee3079 100644 --- a/src/uucore/src/lib/features/format/mod.rs +++ b/src/uucore/src/lib/features/format/mod.rs @@ -92,7 +92,7 @@ impl Display for FormatError { "format '{}' has no % directive", String::from_utf8_lossy(s) ), - Self::InvalidPrecision(precision) => write!(f, "invalid precision: '{}'", precision), + Self::InvalidPrecision(precision) => write!(f, "invalid precision: '{precision}'"), // TODO: Error message below needs some work Self::WrongSpecType => write!(f, "wrong % directive type was given"), Self::IoError(_) => write!(f, "io error"),