mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-01 10:52:14 +00:00
Merge pull request #1060 from EXetoC/vm-arithmetic-overflow
Arithmetic underflow/overflow checking for the VM
This commit is contained in:
@@ -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
|
||||
|
||||
11
tests/vm/toverflowopcaddimmint.nim
Normal file
11
tests/vm/toverflowopcaddimmint.nim
Normal file
@@ -0,0 +1,11 @@
|
||||
discard """
|
||||
errormsg: "over- or underflow"
|
||||
"""
|
||||
|
||||
static:
|
||||
proc p =
|
||||
var
|
||||
x = int64.high
|
||||
discard x + 1
|
||||
assert false
|
||||
p()
|
||||
12
tests/vm/toverflowopcaddint.nim
Normal file
12
tests/vm/toverflowopcaddint.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
discard """
|
||||
errormsg: "over- or underflow"
|
||||
"""
|
||||
|
||||
static:
|
||||
proc p =
|
||||
var
|
||||
x = int64.high
|
||||
y = 1
|
||||
discard x + y
|
||||
assert false
|
||||
p()
|
||||
11
tests/vm/toverflowopcmulint.nim
Normal file
11
tests/vm/toverflowopcmulint.nim
Normal file
@@ -0,0 +1,11 @@
|
||||
discard """
|
||||
errormsg: "over- or underflow"
|
||||
"""
|
||||
|
||||
static:
|
||||
proc p =
|
||||
var
|
||||
x = 1 shl 62
|
||||
discard x * 2
|
||||
assert false
|
||||
p()
|
||||
10
tests/vm/toverflowopcsubimmint.nim
Normal file
10
tests/vm/toverflowopcsubimmint.nim
Normal file
@@ -0,0 +1,10 @@
|
||||
discard """
|
||||
errormsg: "over- or underflow"
|
||||
"""
|
||||
|
||||
static:
|
||||
proc p =
|
||||
var x = int64.low
|
||||
discard x - 1
|
||||
assert false
|
||||
p()
|
||||
12
tests/vm/toverflowopcsubint.nim
Normal file
12
tests/vm/toverflowopcsubint.nim
Normal file
@@ -0,0 +1,12 @@
|
||||
discard """
|
||||
errormsg: "over- or underflow"
|
||||
"""
|
||||
|
||||
static:
|
||||
proc p =
|
||||
var
|
||||
x = int64.low
|
||||
y = 1
|
||||
discard x - y
|
||||
assert false
|
||||
p()
|
||||
Reference in New Issue
Block a user