difftreelog
feat(evaluator) number overflow checks
in: master
2 files changed
crates/jrsonnet-evaluator/src/evaluate.rsdiffbeforeafterboth929293 (Val::Obj(v1), Val::Obj(v2)) => Val::Obj(v2.with_super(v1.clone())),93 (Val::Obj(v1), Val::Obj(v2)) => Val::Obj(v2.with_super(v1.clone())),94 (Val::Arr(a), Val::Arr(b)) => Val::Arr(Rc::new([&a[..], &b[..]].concat())),94 (Val::Arr(a), Val::Arr(b)) => Val::Arr(Rc::new([&a[..], &b[..]].concat())),95 (Val::Num(v1), Val::Num(v2)) => Val::Num(v1 + v2),95 (Val::Num(v1), Val::Num(v2)) => Val::new_checked_num(v1 + v2)?,96 _ => create_error_result(Error::BinaryOperatorDoesNotOperateOnValues(96 _ => create_error_result(Error::BinaryOperatorDoesNotOperateOnValues(97 BinaryOpType::Add,97 BinaryOpType::Add,98 a.value_type()?,98 a.value_type()?,135 (Val::Str(v1), BinaryOpType::Gte, Val::Str(v2)) => Val::Bool(v1 >= v2),135 (Val::Str(v1), BinaryOpType::Gte, Val::Str(v2)) => Val::Bool(v1 >= v2),136136137 // Num X Num137 // Num X Num138 (Val::Num(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::Num(v1 * v2),138 (Val::Num(v1), BinaryOpType::Mul, Val::Num(v2)) => Val::new_checked_num(v1 * v2)?,139 (Val::Num(v1), BinaryOpType::Div, Val::Num(v2)) => {139 (Val::Num(v1), BinaryOpType::Div, Val::Num(v2)) => {140 if *v2 <= f64::EPSILON {140 if *v2 <= f64::EPSILON {141 create_error_result(crate::Error::DivisionByZero)?141 create_error_result(crate::Error::DivisionByZero)?142 }142 }143 Val::Num(v1 / v2)143 Val::new_checked_num(v1 / v2)?144 }144 }145145146 (Val::Num(v1), BinaryOpType::Sub, Val::Num(v2)) => Val::Num(v1 - v2),146 (Val::Num(v1), BinaryOpType::Sub, Val::Num(v2)) => Val::new_checked_num(v1 - v2)?,147147148 (Val::Num(v1), BinaryOpType::Lt, Val::Num(v2)) => Val::Bool(v1 < v2),148 (Val::Num(v1), BinaryOpType::Lt, Val::Num(v2)) => Val::Bool(v1 < v2),149 (Val::Num(v1), BinaryOpType::Gt, Val::Num(v2)) => Val::Bool(v1 > v2),149 (Val::Num(v1), BinaryOpType::Gt, Val::Num(v2)) => Val::Bool(v1 > v2),644 Literal(LiteralType::Null) => Val::Null,644 Literal(LiteralType::Null) => Val::Null,645 Parened(e) => evaluate(context, e)?,645 Parened(e) => evaluate(context, e)?,646 Str(v) => Val::Str(v.clone()),646 Str(v) => Val::Str(v.clone()),647 Num(v) => Val::Num(*v),647 Num(v) => Val::new_checked_num(*v)?,648 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, &v1, *o, &v2)?,648 BinaryOp(v1, o, v2) => evaluate_binary_op_special(context, &v1, *o, &v2)?,649 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,649 UnaryOp(o, v) => evaluate_unary_op(*o, &evaluate(context, v)?)?,650 Var(name) => push(loc, "var", || {650 Var(name) => push(loc, "var", || {crates/jrsonnet-evaluator/src/val.rsdiffbeforeafterboth--- a/crates/jrsonnet-evaluator/src/val.rs
+++ b/crates/jrsonnet-evaluator/src/val.rs
@@ -134,6 +134,15 @@
};
}
impl Val {
+ /// Creates Val::Num after checking for overflow. As numbers are f64, we can just check for finity
+ pub fn new_checked_num(num: f64) -> Result<Val> {
+ if num.is_finite() {
+ Ok(Val::Num(num))
+ } else {
+ create_error_result(Error::RuntimeError("overflow".into()))
+ }
+ }
+
pub fn assert_type(&self, context: &'static str, val_type: ValType) -> Result<()> {
let this_type = self.value_type()?;
if this_type != val_type {