diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2014-04-02 19:59:26 +0200 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2014-04-02 19:59:26 +0200 |
commit | e810c760fd602a2de0386714fc333a8a5df8afeb (patch) | |
tree | 80b84ec242d3ecb525d47e0da98f3061aaa270c4 | |
parent | 207874aa2d80035d0f9e72981cec78ba3ab12260 (diff) | |
parent | c75b247a90e7e51c4ca9e8bb6ecbd823c820609c (diff) | |
download | Nim-e810c760fd602a2de0386714fc333a8a5df8afeb.tar.gz |
Merge pull request #1060 from EXetoC/vm-arithmetic-overflow
Arithmetic underflow/overflow checking for the VM
-rw-r--r-- | compiler/vm.nim | 55 | ||||
-rw-r--r-- | tests/vm/toverflowopcaddimmint.nim | 11 | ||||
-rw-r--r-- | tests/vm/toverflowopcaddint.nim | 12 | ||||
-rw-r--r-- | tests/vm/toverflowopcmulint.nim | 11 | ||||
-rw-r--r-- | tests/vm/toverflowopcsubimmint.nim | 10 | ||||
-rw-r--r-- | tests/vm/toverflowopcsubint.nim | 12 |
6 files changed, 105 insertions, 6 deletions
diff --git a/compiler/vm.nim b/compiler/vm.nim index 0d5386502..7355e85fe 100644 --- a/compiler/vm.nim +++ b/compiler/vm.nim @@ -495,18 +495,46 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = else: stackTrace(c, tos, pc, errNilAccess) of opcAddInt: decodeBC(rkInt) - regs[ra].intVal = regs[rb].intVal + regs[rc].intVal + let + bVal = regs[rb].intVal + cVal = regs[rc].intVal + sum = bVal +% cVal + if (sum xor bVal) >= 0 or (sum xor cVal) >= 0: + regs[ra].intVal = sum + else: + stackTrace(c, tos, pc, errOverOrUnderflow) of opcAddImmInt: decodeBImm(rkInt) #message(c.debug[pc], warnUser, "came here") #debug regs[rb].node - regs[ra].intVal = regs[rb].intVal + imm + let + bVal = regs[rb].intVal + cVal = imm + sum = bVal +% cVal + if (sum xor bVal) >= 0 or (sum xor cVal) >= 0: + regs[ra].intVal = sum + else: + stackTrace(c, tos, pc, errOverOrUnderflow) of opcSubInt: decodeBC(rkInt) - regs[ra].intVal = regs[rb].intVal - regs[rc].intVal + let + bVal = regs[rb].intVal + cVal = regs[rc].intVal + diff = bVal -% cVal + if (diff xor bVal) >= 0 or (diff xor not cVal) >= 0: + regs[ra].intVal = diff + else: + stackTrace(c, tos, pc, errOverOrUnderflow) of opcSubImmInt: decodeBImm(rkInt) - regs[ra].intVal = regs[rb].intVal - imm + let + bVal = regs[rb].intVal + cVal = imm + diff = bVal -% cVal + if (diff xor bVal) >= 0 or (diff xor not cVal) >= 0: + regs[ra].intVal = diff + else: + stackTrace(c, tos, pc, errOverOrUnderflow) of opcLenSeq: decodeBImm(rkInt) #assert regs[rb].kind == nkBracket @@ -539,7 +567,18 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = regs[ra].intVal = nimsets.cardSet(regs[rb].node) of opcMulInt: decodeBC(rkInt) - regs[ra].intVal = regs[rb].intVal * regs[rc].intVal + let + bVal = regs[rb].intVal + cVal = regs[rc].intVal + product = bVal *% cVal + floatProd = toBiggestFloat(bVal) * toBiggestFloat(cVal) + resAsFloat = toBiggestFloat(product) + if resAsFloat == floatProd: + regs[ra].intVal = product + elif 32.0 * abs(resAsFloat - floatProd) <= abs(floatProd): + regs[ra].intVal = product + else: + stackTrace(c, tos, pc, errOverOrUnderflow) of opcDivInt: decodeBC(rkInt) if regs[rc].intVal == 0: stackTrace(c, tos, pc, errConstantDivisionByZero) @@ -632,7 +671,11 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg = of opcUnaryMinusInt: decodeB(rkInt) assert regs[rb].kind == rkInt - regs[ra].intVal = -regs[rb].intVal + let val = regs[rb].intVal + if val != int64.low: + regs[ra].intVal = -val + else: + stackTrace(c, tos, pc, errOverOrUnderflow) of opcUnaryMinusFloat: decodeB(rkFloat) assert regs[rb].kind == rkFloat diff --git a/tests/vm/toverflowopcaddimmint.nim b/tests/vm/toverflowopcaddimmint.nim new file mode 100644 index 000000000..c36b9ed9b --- /dev/null +++ b/tests/vm/toverflowopcaddimmint.nim @@ -0,0 +1,11 @@ +discard """ + errormsg: "over- or underflow" +""" + +static: + proc p = + var + x = int64.high + discard x + 1 + assert false + p() diff --git a/tests/vm/toverflowopcaddint.nim b/tests/vm/toverflowopcaddint.nim new file mode 100644 index 000000000..6d96afc78 --- /dev/null +++ b/tests/vm/toverflowopcaddint.nim @@ -0,0 +1,12 @@ +discard """ + errormsg: "over- or underflow" +""" + +static: + proc p = + var + x = int64.high + y = 1 + discard x + y + assert false + p() diff --git a/tests/vm/toverflowopcmulint.nim b/tests/vm/toverflowopcmulint.nim new file mode 100644 index 000000000..81b3234ba --- /dev/null +++ b/tests/vm/toverflowopcmulint.nim @@ -0,0 +1,11 @@ +discard """ + errormsg: "over- or underflow" +""" + +static: + proc p = + var + x = 1 shl 62 + discard x * 2 + assert false + p() diff --git a/tests/vm/toverflowopcsubimmint.nim b/tests/vm/toverflowopcsubimmint.nim new file mode 100644 index 000000000..09d6f745b --- /dev/null +++ b/tests/vm/toverflowopcsubimmint.nim @@ -0,0 +1,10 @@ +discard """ + errormsg: "over- or underflow" +""" + +static: + proc p = + var x = int64.low + discard x - 1 + assert false + p() diff --git a/tests/vm/toverflowopcsubint.nim b/tests/vm/toverflowopcsubint.nim new file mode 100644 index 000000000..8d114f200 --- /dev/null +++ b/tests/vm/toverflowopcsubint.nim @@ -0,0 +1,12 @@ +discard """ + errormsg: "over- or underflow" +""" + +static: + proc p = + var + x = int64.low + y = 1 + discard x - y + assert false + p() |