Bug 19812 – nested class reference causes dangling reference to out-of-scope struct

Status
REOPENED
Severity
major
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-04-19T12:21:33Z
Last change time
2024-12-13T19:03:07Z
Keywords
pull, safe
Assigned to
No Owner
Creator
hsteoh
See also
https://issues.dlang.org/show_bug.cgi?id=23354
Moved to GitHub: dmd#17904 →

Comments

Comment #0 by hsteoh — 2019-04-19T12:21:33Z
Code: ------ import std.algorithm : filter, map; import std.stdio; struct S { bool flag; auto method() { return [ 1 ].filter!(e => flag); } } void main() @safe { auto s = S(true); writeln(s.method); auto arr = [ s ]; writeln(arr[0].method); auto mappedArray = arr.map!(e => e.method); writeln(mappedArray.front); writeln(mappedArray); } ------ Expected output: [1] [1] [1] [[1]] Actual output: [1] [1] [1] [[]] Changing method() to the following makes the problem go away: ------ auto method() { auto _flag = flag; return [ 1 ].filter!(e => _flag); } ------ Changing flag to an integer value and printing the value reveals that in the last writeln, the value has been corrupted into a garbage value. It appears that the lambda incorrectly closes over a temporary copy of the struct (the argument of map as a local variable) that has gone out of scope by the time the lambda is executed. Explicitly copying .flag into a local variable in method() appears to cause it to be allocated on the heap, as it ought to be. Compiling with -dip25 -dip1000 fails to catch this problem even though main() is marked @safe. Expected behaviour: the compiler should either reject this code (at the very least under -dip25 -dip1000, because the lambda carries a reference to a variable past its scope), or it should do the correct thing by copying the closed-over variable into a heap allocation.
Comment #1 by sahmi.soulaimane — 2019-06-04T12:06:37Z
Another similar case ``` auto makeI(int m) @safe { static struct S { int m; auto inner() { class I { auto get() @safe { return m; } } return new I; } } scope s = S(m); return s.inner(); } void main() @safe { auto i = makeI(5); function() { // clean stack pragma(inline, false); long[0x500] a = 0; }(); assert(i.get() == 5); } ``` https://run.dlang.io/is/xhzYPo
Comment #2 by dlang-bot — 2019-06-04T12:14:32Z
@SSoulaimane created dlang/dmd pull request #9966 "Fix test case - escaping reference to stack struct" mentioning this issue: - issue 19812 - Fix test case, escaping reference to stack struct DMD should catch this https://github.com/dlang/dmd/pull/9966
Comment #3 by dlang-bot — 2019-06-04T13:27:32Z
dlang/dmd pull request #9966 "Fix test case - escaping reference to stack struct" was merged into master: - e62e6e6f68d85682f6a7f664ede871069ec43e12 by سليمان السهمي (Suleyman Sahmi): issue 19812 - Fix test case, escaping reference to stack struct DMD should catch this https://github.com/dlang/dmd/pull/9966
Comment #4 by bugzilla — 2022-08-14T07:25:11Z
(In reply to Suleyman Sahmi (سليمان السهمي) from comment #1) > Another similar case > > ``` > auto makeI(int m) @safe > { > static struct S > { > int m; > auto inner() // adding `return` attribute here > { > class I > { > auto get() @safe { return m; } > } > return new I; > } > } > scope s = S(m); > return s.inner(); // causes correct error returning `s.inner()` escapes a reference to local variable `s` > }
Comment #5 by bugzilla — 2022-08-14T07:31:18Z
The fix appears to be in the `return` inference for auto functions. It should look for returning an instance of a nested class.
Comment #6 by dlang-bot — 2022-08-14T08:51:27Z
@WalterBright created dlang/dmd pull request #14367 "fix Issue 19812 - nested class reference causes dangling reference to…" fixing this issue: - fix Issue 19812 - nested class reference causes dangling reference to out-of-scope struct https://github.com/dlang/dmd/pull/14367
Comment #7 by dlang-bot — 2022-08-31T10:11:33Z
dlang/dmd pull request #14367 "fix Issue 19812 - nested class reference causes dangling reference to…" was merged into master: - 578432b86766890e7383ffd3f3e1ae51e226c49f by Walter Bright: fix Issue 19812 - nested class reference causes dangling reference to out-of-scope struct https://github.com/dlang/dmd/pull/14367
Comment #8 by ibuclaw — 2022-09-21T21:59:31Z
Reopening, as reverted due to issue 23354.
Comment #9 by dlang-bot — 2022-09-27T14:46:42Z
@maxhaton updated dlang/dmd pull request #14482 "Fix Issue 23368 - Don't segfault on throwing null exception" mentioning this issue: - Revert "fix Issue 19812 - nested class reference causes dangling reference to out-of-scope struct (#14367)" This reverts commit 1f244a4f0cc9975a4e1cab3617abf0cbcfabfbc8. https://github.com/dlang/dmd/pull/14482
Comment #10 by robert.schadek — 2024-12-13T19:03:07Z
THIS ISSUE HAS BEEN MOVED TO GITHUB https://github.com/dlang/dmd/issues/17904 DO NOT COMMENT HERE ANYMORE, NOBODY WILL SEE IT, THIS ISSUE HAS BEEN MOVED TO GITHUB