Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix SIGSEGV in VM in opcLdDeref #13865

Merged
merged 1 commit into from
Apr 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 23 additions & 30 deletions compiler/vm.nim
Original file line number Diff line number Diff line change
Expand Up @@ -510,6 +510,23 @@ const
"if you are sure this is not a bug in your code, compile with `--maxLoopIterationsVM:number` (current value: $1)"
errFieldXNotFound = "node lacks field: "


template maybeHandlePtr(node2: PNode, reg: TFullReg, isAssign2: bool): bool =
let node = node2 # prevent double evaluation
if node.kind == nkNilLit:
stackTrace(c, tos, pc, errNilAccess)
let typ = node.typ
if nfIsPtr in node.flags or (typ != nil and typ.kind == tyPtr):
assert node.kind == nkIntLit, $(node.kind)
assert typ != nil
let typ2 = if typ.kind == tyPtr: typ[0] else: typ
if not derefPtrToReg(node.intVal, typ2, reg, isAssign = isAssign2):
# tyObject not supported in this context
stackTrace(c, tos, pc, "deref unsupported ptr type: " & $(typeToString(typ), typ.kind))
true
else:
false

proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
var pc = start
var tos = tos
Expand Down Expand Up @@ -755,26 +772,12 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
ensureKind(regs[rb].regAddr.kind)
regs[ra] = regs[rb].regAddr[]
of rkNode:
if regs[rb].node.kind == nkNilLit:
stackTrace(c, tos, pc, errNilAccess)
if regs[rb].node.kind == nkRefTy:
regs[ra].node = regs[rb].node[0]
else:
let node = regs[rb].node
let typ = node.typ
# see also `nfIsPtr`
if node.kind == nkIntLit:
var typ2 = typ
doAssert typ != nil
if typ.kind == tyPtr:
typ2 = typ2[0]
if not derefPtrToReg(node.intVal, typ2, regs[ra], isAssign = false):
# tyObject not supported in this context
stackTrace(c, tos, pc, "opcLdDeref unsupported ptr type: " & $(typeToString(typ), typ.kind))
else:
## eg: typ.kind = tyObject
ensureKind(rkNode)
regs[ra].node = regs[rb].node
elif not maybeHandlePtr(regs[rb].node, regs[ra], false):
## eg: typ.kind = tyObject
ensureKind(rkNode)
regs[ra].node = regs[rb].node
else:
stackTrace(c, tos, pc, errNilAccess & " kind: " & $regs[rb].kind)
of opcWrDeref:
Expand All @@ -795,18 +798,8 @@ proc rawExecute(c: PCtx, start: int, tos: PStackFrame): TFullReg =
regs[ra].nodeAddr[] = n
of rkRegisterAddr: regs[ra].regAddr[] = regs[rc]
of rkNode:
if regs[ra].node.kind == nkNilLit:
stackTrace(c, tos, pc, errNilAccess)
let node = regs[ra].node
let typ = node.typ
if nfIsPtr in node.flags or (typ != nil and typ.kind == tyPtr):
assert node.kind == nkIntLit, $(node.kind)
var typ2 = typ
if typ.kind == tyPtr:
typ2 = typ2[0]
if not derefPtrToReg(node.intVal, typ2, regs[rc], isAssign = true):
stackTrace(c, tos, pc, "opcWrDeref unsupported ptr type: " & $(typeToString(typ), typ.kind))
else:
# xxx: also check for nkRefTy as in opcLdDeref?
if not maybeHandlePtr(regs[ra].node, regs[rc], true):
regs[ra].node[] = regs[rc].regToNode[]
regs[ra].node.flags.incl nfIsRef
else: stackTrace(c, tos, pc, errNilAccess)
Expand Down
11 changes: 10 additions & 1 deletion tests/vm/tref.nim
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,13 @@ static:
static: # bug #8402
type R = ref object
var empty: R
let otherEmpty = empty
let otherEmpty = empty

block:
# fix https://github.com/timotheecour/Nim/issues/88
template fun() =
var s = @[10,11,12]
var a = s[0].addr
a[] += 100 # was giving SIGSEGV
doAssert a[] == 110
static: fun()