Skip to content

Commit f8dd55e

Browse files
committed
fix never stopping recursion in rune functions lead to a stack overflow
1 parent a0fccf3 commit f8dd55e

File tree

2 files changed

+14
-3
lines changed

2 files changed

+14
-3
lines changed

evaluator.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,16 @@ import (
77
"strings"
88
)
99

10+
const MaxRecursionDepth = 1000 // Between 1000 and 2000 is considered to be a reasonable recursion depth for recursive functions
11+
1012
type Evaluator struct {
1113
// Keep track of file path that have been imported by the import statement.
12-
importedPaths map[string]bool
14+
importedPaths map[string]bool
15+
recursionDepth int
1316
}
1417

1518
func NewEvaluator() *Evaluator {
16-
e := &Evaluator{importedPaths: make(map[string]bool)}
19+
e := &Evaluator{importedPaths: make(map[string]bool), recursionDepth: 0}
1720
return e
1821
}
1922

@@ -34,6 +37,14 @@ func (e *Evaluator) evaluate(exp *Expr, env *Environment) interface{} {
3437
Error(exp, "Null expression error, this is a bug and should never happen!. Please file a bug!")
3538
return nil
3639
}
40+
41+
e.recursionDepth++
42+
defer func() { e.recursionDepth-- }()
43+
44+
if e.recursionDepth > MaxRecursionDepth {
45+
Error(exp, "Maximum recursion depth exceeded")
46+
}
47+
3748
switch exp.Type {
3849
case Num:
3950
return parseNumber(exp.Value.(string), exp)

example/test.rune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
factorial = fun(n) {
2-
if n == 0 then return = 1
2+
if n == 0 then 1
33
n * factorial(n - 1)
44
}
55
println(factorial(5)) # Outputs 120

0 commit comments

Comments
 (0)