1
0
mirror of https://github.com/robertkrimen/otto synced 2025-10-05 19:19:10 +08:00

add simple stack depth limit mechanism

This commit is contained in:
deoxxa 2016-04-04 00:07:41 +10:00
parent 53221230c2
commit c142472392
4 changed files with 64 additions and 0 deletions

View File

@ -367,6 +367,10 @@ func (self Otto) SetRandomSource(fn func() float64) {
self.runtime.random = fn
}
func (self Otto) SetStackDepthLimit(limit int) {
self.runtime.stackLimit = limit
}
// Context is a structure that contains information about the current execution
// context.
type Context struct {

View File

@ -1650,6 +1650,56 @@ func Test_objectLength(t *testing.T) {
})
}
func Test_stackLimit(t *testing.T) {
code := `
function a() {}
function b() { a(); }
function c() { b(); }
function d() { c(); }
function e() { d(); }
e();
`
tt(t, func() {
_, vm := test()
_, err := vm.Run(code)
is(err == nil, true)
})
tt(t, func() {
_, vm := test()
vm.vm.SetStackDepthLimit(2)
_, err := vm.Run(code)
is(err == nil, false)
})
tt(t, func() {
_, vm := test()
vm.vm.SetStackDepthLimit(6)
_, err := vm.Run(code)
is(err == nil, true)
})
tt(t, func() {
_, vm := test()
vm.vm.SetStackDepthLimit(1)
vm.vm.SetStackDepthLimit(0)
_, err := vm.Run(code)
is(err == nil, true)
})
}
func BenchmarkNew(b *testing.B) {
for i := 0; i < b.N; i++ {
New()

View File

@ -56,6 +56,7 @@ type _runtime struct {
eval *_object // The builtin eval, for determine indirect versus direct invocation
debugger func(*Otto)
random func() float64
stackLimit int
labels []string // FIXME
lck sync.Mutex
@ -63,6 +64,14 @@ type _runtime struct {
func (self *_runtime) enterScope(scope *_scope) {
scope.outer = self.scope
if self.scope != nil {
scope.depth = self.scope.depth + 1
}
if self.stackLimit != 0 && scope.depth >= self.stackLimit {
panic(self.panicRangeError("RangeError: Maximum call stack size exceeded"))
}
self.scope = scope
}

View File

@ -21,6 +21,7 @@ type _scope struct {
this *_object
eval bool // Replace this with kind?
outer *_scope
depth int
frame _frame
}