Bug 22854 – static foreach byCodepoint segfault (2.099-rc.1)

Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2022-03-07T13:09:10Z
Last change time
2023-01-01T06:25:09Z
Keywords
pull
Assigned to
No Owner
Creator
FeepingCreature

Comments

Comment #0 by default_357-line — 2022-03-07T13:09:10Z
import std.uni; void main() { static foreach (ch; unicode.Control.byCodepoint) { } } This segfaults on DMD 2.099-rc.1. From looking at the longer DMD debug mode backtrace on master, there seems to be a stack variable destructor call that reads dead stack memory?
Comment #1 by dkorpel — 2022-03-07T15:20:25Z
digger bisect: ``` digger: 8be5c8b0111b68ca23e23c36a6fd1cc746a9c0cc is the first bad commit commit 8be5c8b0111b68ca23e23c36a6fd1cc746a9c0cc Author: Iain Buclaw <[email protected]> Date: Wed Jun 9 12:34:57 2021 +0200 dmd: static foreach: Delay running ctfeInterpret until the lowering stage ```
Comment #2 by default_357-line — 2022-03-07T16:37:32Z
Further reduced: void main() { static foreach (ch; SomeContainer().range) { } } struct SomeContainer { SomeRange range() { return SomeRange(); } TypeWithDestructor data; } struct TypeWithDestructor { ~this() { } } struct SomeRange { int front() { return 0; } bool empty() { return true; } void popFront() { } }
Comment #3 by ibuclaw — 2022-12-20T16:51:28Z
(In reply to FeepingCreature from comment #0) > From looking at the longer DMD debug mode backtrace on master, there seems > to be a stack variable destructor call that reads dead stack memory? As far as I can tell, possibly an artificial/temporary variable that has not been declared properly.
Comment #4 by ibuclaw — 2022-12-20T17:20:46Z
Tweaking the code to use a regular foreach: --- void main() { foreach (ch; SomeContainer().range) { } } pragma(msg, main()); --- This is where the temporary gets *pushed* onto the CTFE stack. --- // If the comma returns a temporary variable, it needs to be an lvalue // (this is particularly important for struct constructors) if (e.e1.op == EXP.declaration && e.e2.op == EXP.variable && e.e1.isDeclarationExp().declaration == e.e2.isVarExp().var && e.e2.isVarExp().var.storage_class & STC.ctfe) { VarExp ve = e.e2.isVarExp(); VarDeclaration v = ve.var.isVarDeclaration(); ctfeGlobals.stack.push(v); // <--- here --- However for `static foreach`, this is never done because of the equality condition (declaration == var) is not true. This despite both declarationexp and varexp having the same identifier name (__slSomeCo3). Obviously, *something* has been copied that really shouldn't have been.
Comment #5 by dlang-bot — 2022-12-20T17:48:39Z
@ibuclaw created dlang/dmd pull request #14724 "fix Issue 22854 - [REG 2.099-rc.1] static foreach byCodepoint segfault" fixing this issue: - fix Issue 22854 - static foreach byCodepoint segfault (2.099-rc.1) https://github.com/dlang/dmd/pull/14724
Comment #6 by dlang-bot — 2022-12-21T00:04:18Z
dlang/dmd pull request #14724 "fix Issue 22854 - [REG 2.099-rc.1] static foreach byCodepoint segfault" was merged into stable: - 650a3a730abd2d4fa65b126ef4c25f2519470db4 by Iain Buclaw: fix Issue 22854 - static foreach byCodepoint segfault (2.099-rc.1) https://github.com/dlang/dmd/pull/14724
Comment #7 by dlang-bot — 2023-01-01T06:25:09Z
dlang/dmd pull request #14765 "merge stable" was merged into master: - 77935bf4944c257736a3d0d76be3fdaef54cfb60 by Iain Buclaw: fix Issue 22854 - static foreach byCodepoint segfault (2.099-rc.1) https://github.com/dlang/dmd/pull/14765