From 4efece995ed7547f6bc6161c677186cc9ae6dd67 Mon Sep 17 00:00:00 2001 From: ringabout <43030857+ringabout@users.noreply.github.com> Date: Fri, 7 Nov 2025 17:06:05 +0800 Subject: [PATCH] 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 6f73094263ee83753aa8c3f25f13739c34d78c96) --- compiler/transf.nim | 5 ++++- tests/iter/titer_issues.nim | 25 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/compiler/transf.nim b/compiler/transf.nim index 066be57f87..5d80bf9328 100644 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -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)) diff --git a/tests/iter/titer_issues.nim b/tests/iter/titer_issues.nim index ff0b8eb49f..5070a54713 100644 --- a/tests/iter/titer_issues.nim +++ b/tests/iter/titer_issues.nim @@ -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"