mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 03:27:44 +00:00
seq:add bounds for exponents
Add bounds for exponents to avoid overflow issues for inputs like 'seq 1e-9223372036854775808'
This commit is contained in:
parent
dca0ec0e65
commit
b3c0633b95
2 changed files with 36 additions and 9 deletions
|
@ -103,15 +103,18 @@ fn parse_exponent_no_decimal(s: &str, j: usize) -> Result<PreciseNumber, ParseNu
|
|||
// displayed in decimal notation. For example, "1e-2" will be
|
||||
// displayed as "0.01", but "1e2" will be displayed as "100",
|
||||
// without a decimal point.
|
||||
let x: BigDecimal = {
|
||||
let parsed_decimal = s
|
||||
.parse::<BigDecimal>()
|
||||
.map_err(|_| ParseNumberError::Float)?;
|
||||
if parsed_decimal == BigDecimal::zero() {
|
||||
BigDecimal::zero()
|
||||
} else {
|
||||
parsed_decimal
|
||||
}
|
||||
|
||||
// In ['BigDecimal'], a positive scale represents a negative power of 10.
|
||||
// This means the exponent value from the number must be inverted. However,
|
||||
// since the |i64::MIN| > |i64::MAX| (i.e. |−2^63| > |2^63−1|) inverting a
|
||||
// valid negative value could result in an overflow. To prevent this, we
|
||||
// limit the minimal value with i64::MIN + 1.
|
||||
let exponent = exponent.max(i64::MIN + 1);
|
||||
let base: BigInt = s[..j].parse().map_err(|_| ParseNumberError::Float)?;
|
||||
let x = if base.is_zero() {
|
||||
BigDecimal::zero()
|
||||
} else {
|
||||
BigDecimal::from_bigint(base, -exponent)
|
||||
};
|
||||
|
||||
let num_integral_digits = if is_minus_zero_float(s, &x) {
|
||||
|
@ -599,4 +602,18 @@ mod tests {
|
|||
assert_eq!(num_fractional_digits("-0e-1"), 1);
|
||||
assert_eq!(num_fractional_digits("-0.0e-1"), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_min_exponents() {
|
||||
// Make sure exponents <= i64::MIN do not cause errors
|
||||
assert!("1e-9223372036854775807".parse::<PreciseNumber>().is_ok());
|
||||
assert!("1e-9223372036854775808".parse::<PreciseNumber>().is_ok());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_max_exponents() {
|
||||
// Make sure exponents >= i64::MAX cause errors
|
||||
assert!("1e9223372036854775807".parse::<PreciseNumber>().is_err());
|
||||
assert!("1e9223372036854775808".parse::<PreciseNumber>().is_err());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -878,6 +878,16 @@ fn test_parse_float_gnu_coreutils() {
|
|||
.stdout_only("0.000000\n0.000001\n0.000002\n0.000003\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_out_of_bounds_exponents() {
|
||||
// The value 1e-9223372036854775808 is used in GNU Coreutils and BigDecimal tests to verify
|
||||
// overflows and undefined behavior. Let's test the value too.
|
||||
new_ucmd!()
|
||||
.args(&["1e-9223372036854775808"])
|
||||
.succeeds()
|
||||
.stdout_only("");
|
||||
}
|
||||
|
||||
#[ignore]
|
||||
#[test]
|
||||
fn test_parse_valid_hexadecimal_float_format_issues() {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue