mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
printf: avoid panic on integer precision above u16::MAX
Signed-off-by: Sai Asish Y <say.apm35@gmail.com>
This commit is contained in:
committed by
Daniel Hofstetter
parent
64e536cbe6
commit
452824f8ab
@@ -83,7 +83,7 @@ impl Formatter<i64> for SignedInt {
|
||||
// -i64::MIN is actually 1 larger than i64::MAX, so we need to cast to i128 first.
|
||||
let abs = (x as i128).abs();
|
||||
let s = if self.precision > 0 {
|
||||
format!("{abs:0>width$}", width = self.precision)
|
||||
zero_pad_to(&abs.to_string(), self.precision)
|
||||
} else {
|
||||
abs.to_string()
|
||||
};
|
||||
@@ -153,7 +153,7 @@ impl Formatter<u64> for UnsignedInt {
|
||||
_ => "",
|
||||
};
|
||||
|
||||
s = format!("{prefix}{s:0>width$}", width = self.precision);
|
||||
s = format!("{prefix}{}", zero_pad_to(&s, self.precision));
|
||||
write_output(writer, String::new(), s, self.width, self.alignment)
|
||||
}
|
||||
|
||||
@@ -326,6 +326,23 @@ impl Formatter<&ExtendedBigDecimal> for Float {
|
||||
}
|
||||
}
|
||||
|
||||
/// Left-pad `s` with `'0'` until it is at least `width` characters long.
|
||||
///
|
||||
/// Unlike `format!("{s:0>width$}")`, this does not feed `width` into the
|
||||
/// standard formatting machinery, which panics with "Formatting argument out
|
||||
/// of range" once the dynamic width exceeds `u16::MAX`. A large precision such
|
||||
/// as `%.100000d` is valid input for `printf`/`seq`, so it must not panic.
|
||||
fn zero_pad_to(s: &str, width: usize) -> String {
|
||||
if s.len() >= width {
|
||||
s.to_string()
|
||||
} else {
|
||||
let mut padded = String::with_capacity(width);
|
||||
padded.extend(std::iter::repeat_n('0', width - s.len()));
|
||||
padded.push_str(s);
|
||||
padded
|
||||
}
|
||||
}
|
||||
|
||||
fn get_sign_indicator(sign: PositiveSign, negative: bool) -> String {
|
||||
if negative {
|
||||
String::from("-")
|
||||
@@ -1194,6 +1211,21 @@ mod test {
|
||||
assert_eq!(fmt(&format, -123i64), "-123");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn format_int_large_precision() {
|
||||
// A precision above u16::MAX must not panic in the formatter (#12572).
|
||||
let format = Format::<SignedInt, i64>::parse("%.100000d").unwrap();
|
||||
let s = fmt(&format, 1i64);
|
||||
assert_eq!(s.len(), 100_000);
|
||||
assert!(s.ends_with("01"));
|
||||
assert!(s.starts_with('0'));
|
||||
|
||||
let format = Format::<UnsignedInt, u64>::parse("%.100000x").unwrap();
|
||||
let s = fmt(&format, 255u64);
|
||||
assert_eq!(s.len(), 100_000);
|
||||
assert!(s.ends_with("0ff"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[ignore = "Need issue #7509 to be fixed"]
|
||||
fn format_signed_int_precision_zero() {
|
||||
|
||||
Reference in New Issue
Block a user