Bug 23170 – Array literal passed to map in lambda, then returned from nested function, is memory corrupted

Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2022-06-07T15:37:35Z
Last change time
2022-07-09T16:32:04Z
Keywords
industry, pull
Assigned to
No Owner
Creator
FeepingCreature
See also
https://issues.dlang.org/show_bug.cgi?id=20734

Comments

Comment #0 by default_357-line — 2022-06-07T15:37:35Z
Consider this code: import std.algorithm; import std.conv; import std.range; void main() { auto result = ({ return [1, 2, 3].badMap; })().array; assert(result == [1, 2, 3], result.to!string); } alias badMap = range => range.map!(a => a); Expected: No output. Actual output: [email protected](9): [1, 2, 623040144] (Numbers vary semi-randomly.) Works on DMD 2.091.1. Crashes on 2.092.0, 2.097, 2.099 and 2.100. (Thanks ndf!)
Comment #1 by default_357-line — 2022-06-07T15:44:34Z
(happens with void main() @safe as well)
Comment #2 by default_357-line — 2022-06-07T15:53:22Z
Even weirder reproduction! void main() { test(({ return badAlias([1, 2, 3]); })()); } void test(int[] array) { assert(array[0] == 1); assert(array[1] == 2); assert(array[2] == 3); } alias badAlias = (int[] array) => id(array); int[] id(int[] array) { return array; }
Comment #3 by default_357-line — 2022-06-07T15:59:43Z
It seems like DMD thinks it can stack allocate the array literal?
Comment #4 by ibuclaw — 2022-06-07T17:19:53Z
(In reply to FeepingCreature from comment #3) > It seems like DMD thinks it can stack allocate the array literal? Yes.
Comment #5 by ibuclaw — 2022-06-07T17:20:30Z
(In reply to FeepingCreature from comment #0) > Consider this code: > > import std.algorithm; > import std.conv; > import std.range; > > void main() > { > auto result = ({ return [1, 2, 3].badMap; })().array; > > assert(result == [1, 2, 3], result.to!string); > } > > alias badMap = range => range.map!(a => a); This is the original, but without imports (could use as an extra test). --- template map(fun...) { auto map(int[] r) { static struct MapResult(alias fun) { this(int[] input) { _input = input; } auto length() { return _input.length; } bool empty() { return !_input.length; } auto ref front() { return fun(_input[0]); } void popFront() { _input = _input[1 .. $]; } private int[] _input; } return MapResult!(fun)(r); } } auto array(Range)(Range r) { const length = r.length; if (length == 0) return null; int[] result; result.length = 3; size_t i; foreach (e; r) { result[i] = e; ++i; } assert(i == length); return (() @trusted => cast(int[]) result)(); } void main() { auto result = [1, 2, 3].badMap.dgify()().array; assert(result == [1, 2, 3]); } alias badMap = range => range.map!(a => a); alias dgify = (lazy value) => &value;
Comment #6 by ibuclaw — 2022-06-07T17:25:03Z
Comment #7 by ibuclaw — 2022-06-07T17:37:48Z
Comment #8 by dlang-bot — 2022-06-07T18:16:02Z
@dkorpel created dlang/dmd pull request #14193 "Fix Issue 23170 - Array literal passed to map in lambda, then returne…" fixing this issue: - Fix Issue 23170 - Array literal passed to map in lambda, then returned from nested function, is memory corrupted https://github.com/dlang/dmd/pull/14193
Comment #9 by dlang-bot — 2022-06-08T13:14:23Z
dlang/dmd pull request #14193 "Fix Issue 23170 - Array literal passed to map in lambda, then returne…" was merged into stable: - f192ae3d24d73c566754c5eb2e14dcdd1dbe5549 by dkorpel: Fix Issue 23170 - Array literal passed to map in lambda, then returned from nested function, is memory corrupted https://github.com/dlang/dmd/pull/14193
Comment #10 by dlang-bot — 2022-07-09T16:32:04Z
dlang/dmd pull request #14280 "merge stable" was merged into master: - 954e5b6394a2a5e47cabf9e4ae13a5f3815db71b by Dennis: Fix Issue 23170 - Array literal passed to map in lambda, then returned from nested function, is memory corrupted (#14193) https://github.com/dlang/dmd/pull/14280