Skip to content

Commit

Permalink
Fix compiler fold optimization of "integer divide by zero"
Browse files Browse the repository at this point in the history
  • Loading branch information
antonmedv committed Sep 9, 2020
1 parent e6958d3 commit 7dd2fd3
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 0 deletions.
11 changes: 11 additions & 0 deletions expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand Down
16 changes: 16 additions & 0 deletions optimizer/fold.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {}
Expand Down Expand Up @@ -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})
}
}
Expand Down
3 changes: 3 additions & 0 deletions optimizer/optimizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
Expand Down

0 comments on commit 7dd2fd3

Please sign in to comment.