[Issue 20148] void initializated bool can be both true and false

d-bugmail at puremagic.com d-bugmail at puremagic.com
Fri Jun 5 23:31:09 UTC 2020


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

hsteoh at quickfur.ath.cx changed:

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

--- Comment #2 from hsteoh at quickfur.ath.cx ---
There's more to it than a hole in @safe.  Look at the disassembly below, there
seems to be a codegen bug as well:

-------------------
000000000003f698 <_Dmain>:
   3f698:       55                      push   %rbp
   3f699:       48 8b ec                mov    %rsp,%rbp
   3f69c:       48 83 ec 10             sub    $0x10,%rsp
   3f6a0:       40 8a 7d f8             mov    -0x8(%rbp),%dil
   3f6a4:       e8 07 00 00 00          callq  3f6b0 <@trusted void
test.f(bool)>
   3f6a9:       31 c0                   xor    %eax,%eax
   3f6ab:       c9                      leaveq
   3f6ac:       c3                      retq
   3f6ad:       00 00                   add    %al,(%rax)
        ...

000000000003f6b0 <@trusted void test.f(bool)>:
   3f6b0:       55                      push   %rbp
   3f6b1:       48 8b ec                mov    %rsp,%rbp
   3f6b4:       48 83 ec 20             sub    $0x20,%rsp
   3f6b8:       89 7d f8                mov    %edi,-0x8(%rbp)
   3f6bb:       c6 45 e8 00             movb   $0x0,-0x18(%rbp)
   3f6bf:       40 80 7d f8 00          rex cmpb $0x0,-0x8(%rbp)
   3f6c4:       74 06                   je     3f6cc <@trusted void
test.f(bool)+0x1c>
   3f6c6:       48 8d 45 e8             lea    -0x18(%rbp),%rax
   3f6ca:       eb 0a                   jmp    3f6d6 <@trusted void
test.f(bool)+0x26>
   3f6cc:       bf 01 00 00 00          mov    $0x1,%edi
   3f6d1:       e8 9a fc ff ff          callq  3f370 <malloc at plt>
   3f6d6:       48 89 45 f0             mov    %rax,-0x10(%rbp)
   3f6da:       8a 4d f8                mov    -0x8(%rbp),%cl
   3f6dd:       80 f1 01                xor    $0x1,%cl
   3f6e0:       74 09                   je     3f6eb <@trusted void
test.f(bool)+0x3b>
   3f6e2:       48 8b 7d f0             mov    -0x10(%rbp),%rdi
   3f6e6:       e8 65 f9 ff ff          callq  3f050 <free at plt>
   3f6eb:       c9                      leaveq
   3f6ec:       c3                      retq
---------------

In main(), the value of -0x8(%rbp), apparently where main.b is stored, is
loaded into the lower register %dil. But in f(), the value of the entire
register %edi is stored in a local variable (coincidentally -0x8(%rbp), but
points to a different place because this is now the local scope of the callee).
Then a few instructions down this local variable is tested for having all 0's
in its value: even though only the lower part of the register was actually
loaded in main!

Then after the if-statement, the (lower byte of the) local variable -0x8(%rbp)
is loaded into %cl and compared against a literal 1.

Even though technically this codegen works if b is either 0 or 1, it seems
inconsistent at best (why compare the entire 32-bit value to 0 when checking
for false, but only the lower byte when checking for true?), and in this case
outright wrong when b is uninitialized and therefore can have any random
garbage value other than 0 or 1.

--


More information about the Digitalmars-d-bugs mailing list