diff --git a/expr_test.go b/expr_test.go index 7a9fcb882..9da5fb49d 100644 --- a/expr_test.go +++ b/expr_test.go @@ -1142,6 +1142,17 @@ func TestIssue_nested_closures(t *testing.T) { require.True(t, output.(bool)) } +func TestIssue138(t *testing.T) { + env := map[string]interface{}{} + + _, err := expr.Compile(`1 / (1 - 1)`, expr.Env(env)) + require.Error(t, err) + require.Equal(t, "integer divide by zero (1:3)\n | 1 / (1 - 1)\n | ..^", err.Error()) + + _, err = expr.Compile(`1 % 0`, expr.Env(env)) + require.Error(t, err) +} + // // Mock types // diff --git a/optimizer/fold.go b/optimizer/fold.go index b88163c66..666912541 100644 --- a/optimizer/fold.go +++ b/optimizer/fold.go @@ -5,10 +5,12 @@ import ( "reflect" . "github.com/antonmedv/expr/ast" + "github.com/antonmedv/expr/file" ) type fold struct { applied bool + err *file.Error } func (*fold) Enter(*Node) {} @@ -65,12 +67,26 @@ func (fold *fold) Exit(node *Node) { case "/": if a, ok := n.Left.(*IntegerNode); ok { if b, ok := n.Right.(*IntegerNode); ok { + if b.Value == 0 { + fold.err = &file.Error{ + Location: (*node).Location(), + Message: "integer divide by zero", + } + return + } patchWithType(&IntegerNode{Value: a.Value / b.Value}, a.Type()) } } case "%": if a, ok := n.Left.(*IntegerNode); ok { if b, ok := n.Right.(*IntegerNode); ok { + if b.Value == 0 { + fold.err = &file.Error{ + Location: (*node).Location(), + Message: "integer divide by zero", + } + return + } patch(&IntegerNode{Value: a.Value % b.Value}) } } diff --git a/optimizer/optimizer.go b/optimizer/optimizer.go index 74319641d..738348dc3 100644 --- a/optimizer/optimizer.go +++ b/optimizer/optimizer.go @@ -10,6 +10,9 @@ func Optimize(node *Node, config *conf.Config) error { for limit := 1000; limit >= 0; limit-- { fold := &fold{} Walk(node, fold) + if fold.err != nil { + return fold.err + } if !fold.applied { break }