VM: endless loop prevention

This commit is contained in:
Araq 2014-03-24 08:43:57 +01:00
commit ee1192679e
4 changed files with 33 additions and 1213 deletions

View file

@ -68,7 +68,9 @@ proc stackTrace(c: PCtx, tos: PStackFrame, pc: int,
msg: TMsgKind, arg = "") =
msgWriteln("stack trace: (most recent call last)")
stackTraceAux(c, tos, pc)
localError(c.debug[pc], msg, arg)
# XXX test if we want 'globalError' for every mode
if c.mode == emRepl: globalError(c.debug[pc], msg, arg)
else: localError(c.debug[pc], msg, arg)
proc bailOut(c: PCtx; tos: PStackFrame) =
stackTrace(c, tos, c.exceptionInstr, errUnhandledExceptionX,
@ -333,6 +335,16 @@ proc compile(c: PCtx, s: PSym): int =
when debugEchoCode: c.echoCode result
#c.echoCode
template handleJmpBack() {.dirty.} =
if c.loopIterations <= 0:
if allowInfiniteLoops in c.features:
c.loopIterations = MaxLoopIterations
else:
msgWriteln("stack trace: (most recent call last)")
stackTraceAux(c, tos, pc)
globalError(c.debug[pc], errTooManyIterations)
dec(c.loopIterations)
proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
var pc = start
var tos = tos
@ -735,6 +747,9 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
globalError(c.debug[pc], errGenerated, "VM not built with FFI support")
elif prc.kind != skTemplate:
let newPc = compile(c, prc)
# tricky: a recursion is also a jump back, so we use the same
# logic as for loops:
if newPc < pc: handleJmpBack()
#echo "new pc ", newPc, " calling: ", prc.name.s
var newFrame = PStackFrame(prc: prc, comesFrom: pc, next: tos)
newSeq(newFrame.slots, prc.offset)
@ -778,6 +793,10 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
# jump Bx
let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
inc pc, rbx
of opcJmpBack:
let rbx = instr.regBx - wordExcess - 1 # -1 for the following 'inc pc'
inc pc, rbx
handleJmpBack()
of opcBranch:
# we know the next instruction is a 'fjmp':
let branch = c.constants[instr.regBx-wordExcess]