[Issue 8899] New: Erroneous delegate usage and map template
d-bugmail at puremagic.com
d-bugmail at puremagic.com
Fri Oct 26 13:44:52 PDT 2012
http://d.puremagic.com/issues/show_bug.cgi?id=8899
Summary: Erroneous delegate usage and map template
Product: D
Version: unspecified
Platform: All
OS/Version: All
Status: NEW
Severity: normal
Priority: P2
Component: DMD
AssignedTo: nobody at puremagic.com
ReportedBy: maxim at maxim-fomin.ru
--- Comment #0 from Maxim Fomin <maxim at maxim-fomin.ru> 2012-10-26 13:44:49 PDT ---
Currently dmd incorrectly treats delegates declared when type of parameter is
omitted:
------------------------
import std.stdio;
void main()
{
auto x = 0;
writeln(typeof(a=>x).stringof);
writeln(typeof((int a)=>x).stringof);
writeln(typeof(delegate (a) { return x; }).stringof);
writeln(typeof(delegate (int a) { return x; }).stringof);
}
-------------------------
This is available at dpaste http://dpaste.dzfl.pl/738f7301
The way map template accepts function parameter allows to hide type mismatch
(if a=>c is used in other contexts, dmd will complain about inability to deduct
arguments of type void).
Exploit example is below:
-----main.d--------------
version (bug)
{
import std.string;
}
import test;
void main()
{
testfun();
}
-------test.d-----------
import std.algorithm;
import std.stdio;
void testfun()
{
int c = 0;
writeln([0].map!(a=>c)[0]);
}
-------------------------
Depending on whether bug version is set or not, the program may run correctly
or not. The only significant difference in generated code is in lambda
function. In correct version it takes local value from -30(%rdx), in the broken
version from (%rdx). It may seem wired how importing standard module can change
behavior.
Fixing syntax to delegate(int a) {} or (int a) => helps.
Probably the bug comes from how dmd arranges code generation. If main.d
includes std.string (or other heavily templated module) it is forced to
instantiate templates when it generates code for main module even if they are
irrelevant. However, because main imports test, it instantiates map template
and generates delegate before code of test function is generated.
Relevant parts of compilation logs of runnable and buggy versions:
----buggy.txt-----
import object
import std.string //imported, forcing instantiation during main codegen
.....
code main
function D main
function std.array.empty!(int).empty
function std.array.popFront!(int[]).popFront
function std.array.front!(int).front
function test.testfun.MapResult!(__lambda2,int[]).MapResult.back
function test.testfun.MapResult!(__lambda2,int[]).MapResult.popBack
function test.testfun.MapResult!(__lambda2,int[]).MapResult.this
function test.testfun.MapResult!(__lambda2,int[]).MapResult.empty
function test.testfun.MapResult!(__lambda2,int[]).MapResult.popFront
function test.testfun.MapResult!(__lambda2,int[]).MapResult.front
function test.testfun.MapResult!(__lambda2,int[]).MapResult.opIndex
function test.testfun.MapResult!(__lambda2,int[]).MapResult.length
function test.testfun.MapResult!(__lambda2,int[]).MapResult.opSlice
function test.testfun.MapResult!(__lambda2,int[]).MapResult.save
....
function test.testfun.__lambda2!(int).__lambda2 // testfunc isn't yet
generated
....
code test
function test.testfun
function test.testfun.map!(__lambda2).map!(int[]).map
----runnable.txt-------
code main
function D main
code test
function test.testfun
function std.array.empty!(int).empty
function std.array.popFront!(int[]).popFront
function std.array.front!(int).front
function test.testfun.map!(__lambda2).map!(int[]).map
function test.testfun.MapResult!(__lambda2,int[]).MapResult.back
function test.testfun.MapResult!(__lambda2,int[]).MapResult.popBack
function test.testfun.MapResult!(__lambda2,int[]).MapResult.this
function test.testfun.MapResult!(__lambda2,int[]).MapResult.empty
function test.testfun.MapResult!(__lambda2,int[]).MapResult.popFront
function test.testfun.MapResult!(__lambda2,int[]).MapResult.front
function test.testfun.MapResult!(__lambda2,int[]).MapResult.opIndex
function test.testfun.MapResult!(__lambda2,int[]).MapResult.length
function test.testfun.MapResult!(__lambda2,int[]).MapResult.opSlice
function test.testfun.MapResult!(__lambda2,int[]).MapResult.save
.....
function test.testfun.__lambda2!(int).__lambda2
------------------------
So, probably the problem is in generating delegate before generating function
which local variables are accessed by delegate.
This issue summarizes information from following issues:
- 8514 : delegate and map leads to segfault, importing standard module affects
behavior
- 8854 : as described above
- 8832 : similar code which uses map and delegate has different and incorrect
behavior
- 5064 (???): program crashes when using map and delegate
- 7978 : map, take and iota functions with delegates
--
Configure issuemail: http://d.puremagic.com/issues/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
More information about the Digitalmars-d-bugs
mailing list