digitalmars.D.bugs - [Issue 19122] New: Multiple destruction of union members
- d-bugmail puremagic.com (54/54) Jul 27 2018 https://issues.dlang.org/show_bug.cgi?id=19122
https://issues.dlang.org/show_bug.cgi?id=19122 Issue ID: 19122 Summary: Multiple destruction of union members Product: D Version: D2 Hardware: x86 OS: Windows Status: NEW Keywords: safe Severity: critical Priority: P1 Component: dmd Assignee: nobody puremagic.com Reporter: simen.kjaras gmail.com safe unittest { import std.stdio : writeln; struct S1 { int* p; ~this() { writeln("Writing garbage to random memory: ", p); //*p = 80085; } } struct S2 { union { S1 a; int b; } int index; this(S1 s) { a = s; index = 0; } this(int n) { b = n; index = 1; } } S2 s = 123456; } The above code shows that destructors of union members will be called when the surrounding struct is destructed. In this case, this leads to reinterpretation of an int as a pointer, but worse could happen. If multiple union members have destructors, all of them are called, regardless of what's currently in the union. According to https://github.com/dlang/dmd/pull/5830: "Unrestricted unions can have fields that have destructors, postblits, or invariants. It's up to the user to call them correctly, the compiler does not automatically generate calls to them." This is clearly not what's happening here. Worse, there's no way to tell the compiler not to call the destructors, short of hiding the actual types behind ubyte[]/void[] and casting. As a crowning achievement, this happens in safe. --
Jul 27 2018