Thread overview | |||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
November 01, 2022 [Issue 23445] Can leak scope variable through delegate context | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23445 Walter Bright <bugzilla@digitalmars.com> changed: What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED CC| |bugzilla@digitalmars.com Resolution|--- |INVALID --- Comment #1 from Walter Bright <bugzilla@digitalmars.com> --- Reducing to: int global; int* foo(scope int* p)@safe{ auto dg=(return scope int* q)@safe return scope{ return p; }; return dg(&global); <== returns a pointer to p } This is not a problem, because the compiler recognizes the escape of p and allocates p in a closure on the heap. This heap allocate is done whenever a nested function is turned into a delegate. For nested functions not turned into a delegate, p is placed in a heap allocated closure, and an error is produced for `return dg(&global);` -- |
November 01, 2022 [Issue 23445] Can leak scope variable through delegate context | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23445 timon.gehr@gmx.ch changed: What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |REOPENED Resolution|INVALID |--- --- Comment #2 from timon.gehr@gmx.ch --- My initial example literally escapes a reference to a dead stack variable in `@safe` code. Of course this is a problem. -- |
November 01, 2022 [Issue 23445] Can leak scope variable through delegate context | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23445 Tejas_Garhewal <scienticman@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |scienticman@gmail.com --- Comment #3 from Tejas_Garhewal <scienticman@gmail.com> --- The following code (It's timon's except it calls a couple more intermediate functions): ```d import std.stdio:writeln; int global; int* foo(scope int* p)@safe{ auto dg=(return scope int* q)@safe return scope{ return p; }; return dg(&global); } auto qux()@safe{ int x=10; int* p=&x; int* q=foo(p); return q; } void func(int[6] a) @safe{ int[6] b = a.dup; int[6] c = a.dup; writeln(a, b, c); } void main()@safe{ import std.stdio; auto p=qux(); version(SMASH_STACK) writeln("smashing stack"); func([1,2,3,4,5,6]); func([0,8,2,0,9,7]); writeln(*p); func([0,8,2,9,6,1]); writeln(*p); } ``` When executing via normal dmd, the output is: smashing stack [1, 2, 3, 4, 5, 6][1, 2, 3, 4, 5, 6][1, 2, 3, 4, 5, 6] [0, 8, 2, 0, 9, 7][0, 8, 2, 0, 9, 7][0, 8, 2, 0, 9, 7] -960565922 [0, 8, 2, 9, 6, 1][0, 8, 2, 9, 6, 1][0, 8, 2, 9, 6, 1] -960565848 <----- Notice the value changing if read after invoking another function When executed via dmd-beta, the output is: smashing stack [1, 2, 3, 4, 5, 6][1, 2, 3, 4, 5, 6][1, 2, 3, 4, 5, 6] [0, 8, 2, 0, 9, 7][0, 8, 2, 0, 9, 7][0, 8, 2, 0, 9, 7] -1630675618 [0, 8, 2, 9, 6, 1][0, 8, 2, 9, 6, 1][0, 8, 2, 9, 6, 1] -1630675544 <-------- Ditto When executed via ldc, the output is: smashing stack [1, 2, 3, 4, 5, 6][1, 2, 3, 4, 5, 6][1, 2, 3, 4, 5, 6] [0, 8, 2, 0, 9, 7][0, 8, 2, 0, 9, 7][0, 8, 2, 0, 9, 7] 21942 [0, 8, 2, 9, 6, 1][0, 8, 2, 9, 6, 1][0, 8, 2, 9, 6, 1] 21942 <------- Here it doesn't ldc-beta output: smashing stack [1, 2, 3, 4, 5, 6][1, 2, 3, 4, 5, 6][1, 2, 3, 4, 5, 6] [0, 8, 2, 0, 9, 7][0, 8, 2, 0, 9, 7][0, 8, 2, 0, 9, 7] 22061 [0, 8, 2, 9, 6, 1][0, 8, 2, 9, 6, 1][0, 8, 2, 9, 6, 1] 22061 <------- Neither over here Surely this is not expected behaviour? -- |
November 01, 2022 [Issue 23445] Can leak scope variable through delegate context | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23445 Adam D. Ruppe <destructionator@gmail.com> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |destructionator@gmail.com --- Comment #4 from Adam D. Ruppe <destructionator@gmail.com> --- likely same root cause as https://issues.dlang.org/show_bug.cgi?id=23440 -- |
November 01, 2022 [Issue 23445] Can leak scope variable through delegate context | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23445 --- Comment #5 from Walter Bright <bugzilla@digitalmars.com> --- (In reply to timon.gehr from comment #2) > My initial example literally escapes a reference to a dead stack variable in `@safe` code. Of course this is a problem. It is not a stack variable, though. It is allocated on the heap. -- |
November 01, 2022 [Issue 23445] Can leak scope variable through delegate context | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23445 Walter Bright <bugzilla@digitalmars.com> changed: What |Removed |Added ---------------------------------------------------------------------------- See Also| |https://issues.dlang.org/sh | |ow_bug.cgi?id=23440 -- |
November 01, 2022 [Issue 23445] Can leak scope variable through delegate context | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23445 --- Comment #6 from timon.gehr@gmx.ch --- The delegate context is allocated on the heap. There is a `scope int* p` in that context, and this pointer points to the stack variable `x`. `qux` uses `foo` to escape a pointer to the local stack variable `x`. The delegate context is not even being referenced anymore when the UB happens. `foo` is just a device that allows `scope`-laundering an arbitrary pointer. `scope` pointer in, non-`scope` pointer out. -- |
November 01, 2022 [Issue 23445] Can leak scope variable through delegate context | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23445 --- Comment #7 from Walter Bright <bugzilla@digitalmars.com> --- (In reply to timon.gehr from comment #6) > The delegate context is allocated on the heap. There is a `scope int* p` in that context, and this pointer points to the stack variable `x`. > > `qux` uses `foo` to escape a pointer to the local stack variable `x`. The delegate context is not even being referenced anymore when the UB happens. `foo` is just a device that allows `scope`-laundering an arbitrary pointer. `scope` pointer in, non-`scope` pointer out. You're right. I was mistaken. -- |
November 02, 2022 [Issue 23445] Can leak scope variable through delegate context | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23445 Dlang Bot <dlang-bot@dlang.rocks> changed: What |Removed |Added ---------------------------------------------------------------------------- Keywords| |pull --- Comment #8 from Dlang Bot <dlang-bot@dlang.rocks> --- @WalterBright created dlang/dmd pull request #14610 "fix Issue 23445 - Can leak scope variable through delegate context" fixing this issue: - fix Issue 23445 - Can leak scope variable through delegate context https://github.com/dlang/dmd/pull/14610 -- |
December 17, 2022 [Issue 23445] Can leak scope variable through delegate context | ||||
---|---|---|---|---|
| ||||
https://issues.dlang.org/show_bug.cgi?id=23445 Iain Buclaw <ibuclaw@gdcproject.org> changed: What |Removed |Added ---------------------------------------------------------------------------- Priority|P1 |P3 -- |
Copyright © 1999-2021 by the D Language Foundation