From c36c527db33da8fc5ef5d8df29c0646b7c45b25d Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Sat, 29 Aug 2026 04:26:18 +0800 Subject: [PATCH] fixes #26143; Possible memory error (#26154) fixes #26143 follows up https://github.com/nim-lang/Nim/pull/20307 --- compiler/injectdestructors.nim | 41 +++++++++++++++++++--------------- tests/arc/tarc_orc.nim | 14 ++++++++++++ 2 files changed, 37 insertions(+), 18 deletions(-) diff --git a/compiler/injectdestructors.nim b/compiler/injectdestructors.nim index ba05ffb6a6..0871a17a60 100644 --- a/compiler/injectdestructors.nim +++ b/compiler/injectdestructors.nim @@ -423,6 +423,20 @@ proc genDefaultCall(t: PType; c: Con; info: TLineInfo): PNode = result.add(newSymNode(createMagic(c.graph, c.idgen, "default", mDefault))) result.typ = t +proc stabilizeBracketIndex(n: PNode; c: var Con; body: var PNode): PNode = + ## Evaluate a side-effecting index once and return the stable access. + doAssert n.kind == nkBracketExpr and not isAtom(n[1]) + let temp = newSym(skLet, getIdent(c.graph.cache, "bracketTmp"), c.idgen, + c.owner, n[1].info) + temp.typ = n[1].typ + let tempAsNode = newSymNode(temp) + body.add newTree(nkLetSection, n[1].info, + newTree(nkIdentDefs, tempAsNode, + newNodeI(nkEmpty, tempAsNode.info), n[1])) + result = copyNode(n) + result.add n[0] + result.add tempAsNode + proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode = # generate: (let tmp = v; reset(v); tmp) if (not hasDestructor(c, n.typ)) and c.inEnsureMove == 0: @@ -434,6 +448,10 @@ proc destructiveMoveVar(n: PNode; c: var Con; s: var Scope): PNode = else: result = newNodeIT(nkStmtListExpr, n.info, n.typ) + var n = n + if n.kind == nkBracketExpr and not isAtom(n[1]): + n = stabilizeBracketIndex(n, c, result) + var temp = newSym(skLet, getIdent(c.graph.cache, "blitTmp"), c.idgen, c.owner, n.info) temp.typ = n.typ var v = newNodeI(nkLetSection, n.info) @@ -1155,24 +1173,11 @@ proc sameLocation*(a, b: PNode): bool = else: false proc genFieldAccessSideEffects(c: var Con; s: var Scope; dest, ri: PNode; flags: set[MoveOrCopyFlag] = {}): PNode = - # with side effects - var temp = newSym(skLet, getIdent(c.graph.cache, "bracketTmp"), c.idgen, c.owner, ri[1].info) - temp.typ = ri[1].typ - var v = newNodeI(nkLetSection, ri[1].info) - let tempAsNode = newSymNode(temp) - - var vpart = newNodeI(nkIdentDefs, tempAsNode.info, 3) - vpart[0] = tempAsNode - vpart[1] = newNodeI(nkEmpty, tempAsNode.info) - vpart[2] = ri[1] - v.add(vpart) - - var newAccess = copyNode(ri) - newAccess.add ri[0] - newAccess.add tempAsNode - - var snk = c.genSink(s, dest, newAccess, flags) - result = newTree(nkStmtList, v, snk, c.genWasMoved(newAccess)) + result = newNodeI(nkStmtList, ri.info) + let newAccess = stabilizeBracketIndex(ri, c, result) + let snk = c.genSink(s, dest, newAccess, flags) + result.add snk + result.add c.genWasMoved(newAccess) proc ownsData(c: var Con; s: var Scope; orig: PNode; flags: set[MoveOrCopyFlag]): PNode = var n = orig diff --git a/tests/arc/tarc_orc.nim b/tests/arc/tarc_orc.nim index 790511314c..9a32d42c6e 100644 --- a/tests/arc/tarc_orc.nim +++ b/tests/arc/tarc_orc.nim @@ -35,6 +35,20 @@ proc bug20303() = bug20303() +block: # bug #26143 + var indexCalls = 0 + + proc nextIndex(): int = + result = indexCalls + inc indexCalls + + proc consume(value: sink string) = + doAssert value == "A" + + var values = @["A", "B"] + consume(values[nextIndex()]) + doAssert indexCalls == 1 + proc main() = # todo bug with templates block: # bug #11267 var a: seq[char] = block: @[]