Skip to content

Commit 6f73094

Browse files
authored
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
1 parent 861ebc0 commit 6f73094

File tree

2 files changed

+29
-1
lines changed

2 files changed

+29
-1
lines changed

compiler/transf.nim

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -828,8 +828,11 @@ proc transformFor(c: PTransf, n: PNode): PNode =
828828
elif t.destructor == nil and arg.typ.destructor != nil:
829829
t = arg.typ
830830

831-
if arg.kind in {nkDerefExpr, nkHiddenDeref}:
831+
if arg.kind in {nkDerefExpr, nkHiddenDeref} and
832+
arg[0].typ.skipTypes(abstractInst).kind != tyLent:
832833
# optimizes for `[]` # bug #24093
834+
# bug #25251: enforce a copy if the arg is a deref of a lent pointer
835+
# since the arg could be a temporary that will go out of scope
833836
var temp = newTemp(c, arg[0].typ, formal.info)
834837
addVar(v, temp)
835838
stmtList.add(newAsgnStmt(c, nkFastAsgn, temp, arg[0], true))

tests/iter/titer_issues.nim

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,3 +432,28 @@ block:
432432
let x = cast[typeof(aaa)](aaa) # not even var
433433
for _ in x[]:
434434
discard
435+
436+
import std/[tables, unicode, sequtils]
437+
438+
const
439+
myTable = {
440+
"en": "abcdefghijklmnopqrstuvwxyz",
441+
}.toTable
442+
443+
proc buggyVersion(locale: string): seq[Rune] =
444+
result = toSeq(runes(myTable[locale]))
445+
446+
proc workingVersion(locale: string): seq[Rune] =
447+
# string lifetime is extended
448+
let str = myTable[locale]
449+
result = toSeq(runes(str))
450+
451+
# echo "Testing working version..."
452+
let runes2 = workingVersion("en")
453+
# echo "Got ", runes2.len, " runes"
454+
455+
# echo "Testing buggy version..."
456+
let runes1 = buggyVersion("en") # <-- CRASHES HERE
457+
458+
doAssert runes1.len == runes2.len
459+
# echo "Got ", runes1.len, " runes"

0 commit comments

Comments
 (0)