Skip to content

Commit 7dd2fd3

Browse files
committed
Fix compiler fold optimization of "integer divide by zero"
1 parent e6958d3 commit 7dd2fd3

File tree

3 files changed

+30
-0
lines changed

3 files changed

+30
-0
lines changed

expr_test.go

+11
Original file line numberDiff line numberDiff line change
@@ -1142,6 +1142,17 @@ func TestIssue_nested_closures(t *testing.T) {
11421142
require.True(t, output.(bool))
11431143
}
11441144

1145+
func TestIssue138(t *testing.T) {
1146+
env := map[string]interface{}{}
1147+
1148+
_, err := expr.Compile(`1 / (1 - 1)`, expr.Env(env))
1149+
require.Error(t, err)
1150+
require.Equal(t, "integer divide by zero (1:3)\n | 1 / (1 - 1)\n | ..^", err.Error())
1151+
1152+
_, err = expr.Compile(`1 % 0`, expr.Env(env))
1153+
require.Error(t, err)
1154+
}
1155+
11451156
//
11461157
// Mock types
11471158
//

optimizer/fold.go

+16
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ import (
55
"reflect"
66

77
. "github.com/antonmedv/expr/ast"
8+
"github.com/antonmedv/expr/file"
89
)
910

1011
type fold struct {
1112
applied bool
13+
err *file.Error
1214
}
1315

1416
func (*fold) Enter(*Node) {}
@@ -65,12 +67,26 @@ func (fold *fold) Exit(node *Node) {
6567
case "/":
6668
if a, ok := n.Left.(*IntegerNode); ok {
6769
if b, ok := n.Right.(*IntegerNode); ok {
70+
if b.Value == 0 {
71+
fold.err = &file.Error{
72+
Location: (*node).Location(),
73+
Message: "integer divide by zero",
74+
}
75+
return
76+
}
6877
patchWithType(&IntegerNode{Value: a.Value / b.Value}, a.Type())
6978
}
7079
}
7180
case "%":
7281
if a, ok := n.Left.(*IntegerNode); ok {
7382
if b, ok := n.Right.(*IntegerNode); ok {
83+
if b.Value == 0 {
84+
fold.err = &file.Error{
85+
Location: (*node).Location(),
86+
Message: "integer divide by zero",
87+
}
88+
return
89+
}
7490
patch(&IntegerNode{Value: a.Value % b.Value})
7591
}
7692
}

optimizer/optimizer.go

+3
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ func Optimize(node *Node, config *conf.Config) error {
1010
for limit := 1000; limit >= 0; limit-- {
1111
fold := &fold{}
1212
Walk(node, fold)
13+
if fold.err != nil {
14+
return fold.err
15+
}
1316
if !fold.applied {
1417
break
1518
}

0 commit comments

Comments
 (0)