mirror of
https://github.com/RGBCube/uutils-coreutils
synced 2025-07-28 19:47:45 +00:00
Fix expr
expr now detects overflows and logs to stderr instead of overflowing the input https://github.com/uutils/coreutils/issues/1194
This commit is contained in:
parent
d5e6259b4c
commit
4756eb5c19
2 changed files with 33 additions and 9 deletions
|
@ -85,18 +85,25 @@ impl ASTNode {
|
|||
ASTNode::Node { ref op_type, .. } => match self.operand_values() {
|
||||
Err(reason) => Err(reason),
|
||||
Ok(operand_values) => match op_type.as_ref() {
|
||||
"+" => infix_operator_two_ints(|a: i64, b: i64| Ok(a + b), &operand_values),
|
||||
"-" => infix_operator_two_ints(|a: i64, b: i64| Ok(a - b), &operand_values),
|
||||
"*" => infix_operator_two_ints(|a: i64, b: i64| Ok(a * b), &operand_values),
|
||||
"/" => infix_operator_two_ints(
|
||||
|a: i64, b: i64| {
|
||||
"+" => infix_operator_two_ints(|a: i64, b: i64| {
|
||||
checked_binop(|| a.checked_add(b), "+")
|
||||
}, &operand_values
|
||||
),
|
||||
"-" => infix_operator_two_ints(|a: i64, b: i64| {
|
||||
checked_binop(|| a.checked_sub(b), "-")
|
||||
}, &operand_values
|
||||
),
|
||||
"*" => infix_operator_two_ints(|a: i64, b: i64| {
|
||||
checked_binop(|| a.checked_mul(b), "*")
|
||||
}, &operand_values
|
||||
),
|
||||
"/" => infix_operator_two_ints(|a: i64, b: i64| {
|
||||
if b == 0 {
|
||||
Err("division by zero".to_owned())
|
||||
} else {
|
||||
Ok(a / b)
|
||||
checked_binop(|| a.checked_div(b), "/")
|
||||
}
|
||||
},
|
||||
&operand_values,
|
||||
}, &operand_values
|
||||
),
|
||||
"%" => infix_operator_two_ints(
|
||||
|a: i64, b: i64| {
|
||||
|
@ -108,7 +115,6 @@ impl ASTNode {
|
|||
},
|
||||
&operand_values,
|
||||
),
|
||||
|
||||
"=" => infix_operator_two_ints_or_two_strings(
|
||||
|a: i64, b: i64| Ok(bool_as_int(a == b)),
|
||||
|a: &String, b: &String| Ok(bool_as_string(a == b)),
|
||||
|
@ -384,6 +390,13 @@ fn move_till_match_paren(
|
|||
}
|
||||
}
|
||||
|
||||
fn checked_binop<F: Fn() -> Option<T>, T>(cb: F, op: &str) -> Result<T, String> {
|
||||
match cb() {
|
||||
Some(v) => Ok(v),
|
||||
None => Err(format!("{}: Numerical result out of range", op)),
|
||||
}
|
||||
}
|
||||
|
||||
fn infix_operator_two_ints<F>(f: F, values: &Vec<String>) -> Result<String, String>
|
||||
where
|
||||
F: Fn(i64, i64) -> Result<i64, String>,
|
||||
|
|
|
@ -12,6 +12,17 @@ fn test_simple_arithmetic() {
|
|||
new_ucmd!().args(&["4", "/", "2"]).run().stdout_is("2\n");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_complex_arithmetic() {
|
||||
let run = new_ucmd!().args(&["9223372036854775807", "+", "9223372036854775807"]).run();
|
||||
run.stdout_is("");
|
||||
run.stderr_is("expr: error: +: Numerical result out of range");
|
||||
|
||||
let run = new_ucmd!().args(&["9", "/", "0"]).run();
|
||||
run.stdout_is("");
|
||||
run.stderr_is("expr: error: division by zero");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parenthesis() {
|
||||
new_ucmd!().args(&["(", "1", "+", "1", ")", "*", "2"]).run().stdout_is("4\n");
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue