diff --git a/src/builtins/units.rs b/src/builtins/units.rs index bdc1b7026..18209f156 100644 --- a/src/builtins/units.rs +++ b/src/builtins/units.rs @@ -95,6 +95,10 @@ fn parse(span: &Span, params: &[Ref], args: &[Value], _strict: bool) -> Re // a stable representation that includes an explicit leading digit. let canonical_part = canonicalize_number_part(number_part); + if exponent_too_large(canonical_part.as_ref()) { + bail!(params[0].span().error("units.parse: exponent too large")); + } + if let Some(e) = ten_exp(suffix) { let combined = combine_decimal_exponent(canonical_part.as_ref(), e) .ok_or_else(|| params[0].span().error("could not parse number"))?; @@ -169,6 +173,12 @@ fn parse_bytes(span: &Span, params: &[Ref], args: &[Value], strict: bool) // a stable representation that includes an explicit leading digit. let canonical_part = canonicalize_number_part(number_part); + if exponent_too_large(canonical_part.as_ref()) { + bail!(params[0] + .span() + .error("units.parse_bytes: exponent too large")); + } + if let Some(e) = twob_exp(suffix) { let mut number = match Number::from_str(canonical_part.as_ref()) { Ok(n) => n, @@ -245,3 +255,11 @@ fn split_decimal_exponent(number: &str) -> Option<(&str, i32)> { let exponent = exp_part.parse::().ok()?; Some((mantissa, exponent)) } + +fn exponent_too_large(number: &str) -> bool { + number + .find(['e', 'E']) + .and_then(|idx| number.get(idx + 1..)) + .map(|exponent| exponent.strip_prefix(['+', '-']).unwrap_or(exponent)) + .is_some_and(|digits| digits.len() > 6) +} diff --git a/tests/interpreter/cases/builtins/units/exponent.yaml b/tests/interpreter/cases/builtins/units/exponent.yaml new file mode 100644 index 000000000..30562d1b9 --- /dev/null +++ b/tests/interpreter/cases/builtins/units/exponent.yaml @@ -0,0 +1,30 @@ +# Copyright (c) Microsoft Corporation. +# Licensed under the MIT License. + +cases: + - note: parse-exponent-too-large + data: {} + modules: + - | + package test + x = units.parse("1e9999999K") + query: data.test.x + error: "units.parse: exponent too large" + + - note: parse-bytes-exponent-too-large + data: {} + modules: + - | + package test + x = units.parse_bytes("1e9999999Ki") + query: data.test.x + error: "units.parse_bytes: exponent too large" + + - note: parse-normal-exponent-ok + data: {} + modules: + - | + package test + x = units.parse("1e6K") + query: data.test.x + want_result: 1e9