[Issue 18232] string variable in toString method of Union: invalid code (crash/segfault)

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri Jan 12 18:18:22 UTC 2018


https://issues.dlang.org/show_bug.cgi?id=18232

hsteoh at quickfur.ath.cx changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |hsteoh at quickfur.ath.cx

--- Comment #1 from hsteoh at quickfur.ath.cx ---
The crash is caused by wrong codegen for the toString() method. Here's a
comparison of a toString() method for a struct vs. for a union:

Struct code:
--------
struct Jack
{
    float f;
    int i;
    string toString()
    {
        string s;
        return s;
    }
}
--------

Generated assembly for Jack.toString:
--------
   447dc:       55                      push   %rbp
   447dd:       48 8b ec                mov    %rsp,%rbp
   447e0:       31 c0                   xor    %eax,%eax
   447e2:       31 d2                   xor    %edx,%edx
   447e4:       5d                      pop    %rbp
   447e5:       c3                      retq   
--------

As can be easily seen, this basically initializes the string s to have
.ptr=null, .length=0, returned by value in %eax and %edx. This is the correct
behaviour.

Union code (basically the same as the struct code, just change 'struct' to
'union'):
--------
union Jack
{
    float f;
    int i;
    string toString()
    {
        string s;
        return s;
    }
}
--------

Generated assembly for Jack.toString:
--------
   4471c:       55                      push   %rbp
   4471d:       48 8b ec                mov    %rsp,%rbp
   44720:       48 83 ec 10             sub    $0x10,%rsp
   44724:       48 8b 55 f8             mov    -0x8(%rbp),%rdx
   44728:       48 8b 45 f0             mov    -0x10(%rbp),%rax
   4472c:       c9                      leaveq 
   4472d:       c3                      retq   
--------

Here, the 'sub' line appears to be allocating space on the stack for a local
variable, presumeably s.  But then it fails to initialize s before loading it
into the return registers %rdx and %rax.  I'm assuming that this is probably
why the allocation of the local variable never got elided, as it was in the
struct case -- the optimizer doesn't see the missing initialization of s, so it
cannot elide the loads from the stack.

So it looks like the bug is caused by failure to initialize s when generating
code for a union vs. a struct.  Why, though, is a mystery to me, since toString
never actually references `this`, so in theory whether `this` is a struct or
union shouldn't matter.

--


More information about the Digitalmars-d-bugs mailing list