fixes #25251; SIGBUS with iterator over const Table lookup - premature temporary destruction (#25255)

fixes #25251

enforce a copy if the arg is a deref of a lent pointer since the arg
could be a temporary that will go out of scope

(cherry picked from commit 6f73094263)
This commit is contained in:
ringabout
2025-11-07 17:06:05 +08:00
committed by narimiran
parent 40e1a34831
commit 4efece995e
2 changed files with 29 additions and 1 deletions

View File

@@ -828,8 +828,11 @@ proc transformFor(c: PTransf, n: PNode): PNode =
elif t.destructor == nil and arg.typ.destructor != nil:
t = arg.typ
if arg.kind in {nkDerefExpr, nkHiddenDeref}:
if arg.kind in {nkDerefExpr, nkHiddenDeref} and
arg[0].typ.skipTypes(abstractInst).kind != tyLent:
# optimizes for `[]` # bug #24093
# bug #25251: enforce a copy if the arg is a deref of a lent pointer
# since the arg could be a temporary that will go out of scope
var temp = newTemp(c, arg[0].typ, formal.info)
addVar(v, temp)
stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg[0], true))

View File

@@ -432,3 +432,28 @@ block:
let x = cast[typeof(aaa)](aaa) # not even var
for _ in x[]:
discard
import std/[tables, unicode, sequtils]
const
myTable = {
"en": "abcdefghijklmnopqrstuvwxyz",
}.toTable
proc buggyVersion(locale: string): seq[Rune] =
result = toSeq(runes(myTable[locale]))
proc workingVersion(locale: string): seq[Rune] =
# string lifetime is extended
let str = myTable[locale]
result = toSeq(runes(str))
# echo "Testing working version..."
let runes2 = workingVersion("en")
# echo "Got ", runes2.len, " runes"
# echo "Testing buggy version..."
let runes1 = buggyVersion("en") # <-- CRASHES HERE
doAssert runes1.len == runes2.len
# echo "Got ", runes1.len, " runes"