@@ -9,6 +9,10 @@ import (
99 "github.com/antonmedv/expr/file"
1010)
1111
12+ var (
13+ MemoryBudget int = 1e6
14+ )
15+
1216func Run (program * Program , env interface {}) (out interface {}, err error ) {
1317 if program == nil {
1418 return nil , fmt .Errorf ("program is nil" )
@@ -40,12 +44,15 @@ type VM struct {
4044 debug bool
4145 step chan struct {}
4246 curr chan int
47+ memory int
48+ limit int
4349}
4450
4551func NewVM (debug bool ) * VM {
4652 vm := & VM {
4753 stack : make ([]interface {}, 0 , 2 ),
4854 debug : debug ,
55+ limit : MemoryBudget ,
4956 }
5057 if vm .debug {
5158 vm .step = make (chan struct {}, 0 )
@@ -64,6 +71,10 @@ func (vm *VM) Run(program *Program, env interface{}) interface{} {
6471 <- vm .step
6572 }
6673
74+ if vm .memory >= vm .limit {
75+ panic ("memory budget exceeded" )
76+ }
77+
6778 vm .pp = vm .ip
6879 vm .ip ++
6980 op := vm .bytecode [vm .pp ]
@@ -198,7 +209,9 @@ func (vm *VM) Run(program *Program, env interface{}) interface{} {
198209 case OpRange :
199210 b := vm .pop ()
200211 a := vm .pop ()
201- vm .push (makeRange (a , b ))
212+ c , size := makeRange (a , b , vm .limit )
213+ vm .push (c )
214+ vm .memory += size
202215
203216 case OpMatches :
204217 b := vm .pop ()
@@ -294,6 +307,7 @@ func (vm *VM) Run(program *Program, env interface{}) interface{} {
294307 array [i ] = vm .pop ()
295308 }
296309 vm .push (array )
310+ vm .memory += size
297311
298312 case OpMap :
299313 size := vm .pop ().(int )
@@ -304,6 +318,7 @@ func (vm *VM) Run(program *Program, env interface{}) interface{} {
304318 m [key .(string )] = value
305319 }
306320 vm .push (m )
321+ vm .memory += size
307322
308323 case OpLen :
309324 vm .push (length (vm .current ()))
0 commit comments