Fix #18079 Illegal storage access compiling call with nested ref/deref (#20738)

* add test case
* refactoring transformAddrDeref and fix #18079
* fix jsgen
This commit is contained in:
Bung 2022-11-04 16:54:45 +08:00 • committed by GitHub
commit ecc8f61fe4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 38 additions and 9 deletions

View file

@ -3046,7 +3046,16 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
of nkObjConstr: genObjConstr(p, n, d) of nkObjConstr: genObjConstr(p, n, d)
of nkCast: genCast(p, n, d) of nkCast: genCast(p, n, d)
of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, d) of nkHiddenStdConv, nkHiddenSubConv, nkConv: genConv(p, n, d)
of nkHiddenAddr, nkAddr: genAddr(p, n, d) of nkHiddenAddr:
if n[0].kind == nkDerefExpr:
# addr ( deref ( x )) --> x
var x = n[0][0]
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
x.typ = n.typ
expr(p, x, d)
return
genAddr(p, n, d)
of nkAddr: genAddr(p, n, d)
of nkBracketExpr: genBracketExpr(p, n, d) of nkBracketExpr: genBracketExpr(p, n, d)
of nkDerefExpr, nkHiddenDeref: genDeref(p, n, d) of nkDerefExpr, nkHiddenDeref: genDeref(p, n, d)
of nkDotExpr: genRecordField(p, n, d) of nkDotExpr: genRecordField(p, n, d)

View file

@ -1422,6 +1422,13 @@ proc genAddr(p: PProc, n: PNode, r: var TCompRes) =
gen(p, n[0], r) gen(p, n[0], r)
of nkHiddenDeref: of nkHiddenDeref:
gen(p, n[0], r) gen(p, n[0], r)
of nkDerefExpr:
var x = n[0]
if n.kind == nkHiddenAddr:
x = n[0][0]
if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
x.typ = n.typ
gen(p, x, r)
of nkHiddenAddr: of nkHiddenAddr:
gen(p, n[0], r) gen(p, n[0], r)
of nkConv: of nkConv:

View file

@ -459,14 +459,14 @@ proc transformYield(c: PTransf, n: PNode): PNode =
for i, child in changeNode: for i, child in changeNode:
child.info = changeNode.info child.info = changeNode.info
proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode = proc transformAddrDeref(c: PTransf, n: PNode, kinds: TNodeKinds): PNode =
result = transformSons(c, n) result = transformSons(c, n)
if c.graph.config.backend == backendCpp or sfCompileToCpp in c.module.flags: return if c.graph.config.backend == backendCpp or sfCompileToCpp in c.module.flags: return
var n = result var n = result
case n[0].kind case n[0].kind
of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64: of nkObjUpConv, nkObjDownConv, nkChckRange, nkChckRangeF, nkChckRange64:
var m = n[0][0] var m = n[0][0]
if m.kind == a or m.kind == b: if m.kind in kinds:
# addr ( nkConv ( deref ( x ) ) ) --> nkConv(x) # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
n[0][0] = m[0] n[0][0] = m[0]
result = n[0] result = n[0]
@ -476,7 +476,7 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode =
result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen) result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
of nkHiddenStdConv, nkHiddenSubConv, nkConv: of nkHiddenStdConv, nkHiddenSubConv, nkConv:
var m = n[0][1] var m = n[0][1]
if m.kind == a or m.kind == b: if m.kind in kinds:
# addr ( nkConv ( deref ( x ) ) ) --> nkConv(x) # addr ( nkConv ( deref ( x ) ) ) --> nkConv(x)
n[0][1] = m[0] n[0][1] = m[0]
result = n[0] result = n[0]
@ -485,7 +485,7 @@ proc transformAddrDeref(c: PTransf, n: PNode, a, b: TNodeKind): PNode =
elif n.typ.skipTypes(abstractInst).kind in {tyVar}: elif n.typ.skipTypes(abstractInst).kind in {tyVar}:
result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen) result.typ = toVar(result.typ, n.typ.skipTypes(abstractInst).kind, c.idgen)
else: else:
if n[0].kind == a or n[0].kind == b: if n[0].kind in kinds:
# addr ( deref ( x )) --> x # addr ( deref ( x )) --> x
result = n[0][0] result = n[0][0]
if n.typ.skipTypes(abstractVar).kind != tyOpenArray: if n.typ.skipTypes(abstractVar).kind != tyOpenArray:
@ -853,7 +853,7 @@ proc transformCall(c: PTransf, n: PNode): PNode =
elif magic == mAddr: elif magic == mAddr:
result = newTransNode(nkAddr, n, 1) result = newTransNode(nkAddr, n, 1)
result[0] = n[1] result[0] = n[1]
result = transformAddrDeref(c, result, nkDerefExpr, nkHiddenDeref) result = transformAddrDeref(c, result, {nkDerefExpr, nkHiddenDeref})
elif magic in {mNBindSym, mTypeOf, mRunnableExamples}: elif magic in {mNBindSym, mTypeOf, mRunnableExamples}:
# for bindSym(myconst) we MUST NOT perform constant folding: # for bindSym(myconst) we MUST NOT perform constant folding:
result = n result = n
@ -1005,10 +1005,12 @@ proc transform(c: PTransf, n: PNode): PNode =
of nkBreakStmt: result = transformBreak(c, n) of nkBreakStmt: result = transformBreak(c, n)
of nkCallKinds: of nkCallKinds:
result = transformCall(c, n) result = transformCall(c, n)
of nkAddr, nkHiddenAddr: of nkHiddenAddr:
result = transformAddrDeref(c, n, nkDerefExpr, nkHiddenDeref) result = transformAddrDeref(c, n, {nkHiddenDeref})
of nkAddr:
result = transformAddrDeref(c, n, {nkDerefExpr, nkHiddenDeref})
of nkDerefExpr, nkHiddenDeref: of nkDerefExpr, nkHiddenDeref:
result = transformAddrDeref(c, n, nkAddr, nkHiddenAddr) result = transformAddrDeref(c, n, {nkAddr, nkHiddenAddr})
of nkHiddenStdConv, nkHiddenSubConv, nkConv: of nkHiddenStdConv, nkHiddenSubConv, nkConv:
result = transformConv(c, n) result = transformConv(c, n)
of nkDiscardStmt: of nkDiscardStmt:

11
tests/misc/t18079.nim Normal file
View file

@ -0,0 +1,11 @@
type
Foo = object
y: int
Bar = object
x: Foo
proc baz(state: var Bar):int =
state.x.y = 2
state.x.y
doAssert baz((ref Bar)(x: (new Foo)[])[]) == 2