[Issue 19122] New: Multiple destruction of union members

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri Jul 27 14:27:22 UTC 2018


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 at puremagic.com
          Reporter: simen.kjaras at 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.

--


More information about the Digitalmars-d-bugs mailing list