Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Assigning enum to static array results in compiler crash (Win64) #2882

Open
KytoDragon opened this issue Oct 25, 2018 · 6 comments
Open

Assigning enum to static array results in compiler crash (Win64) #2882

KytoDragon opened this issue Oct 25, 2018 · 6 comments

Comments

@KytoDragon
Copy link
Contributor

The following code crashes LDC:

enum EMPTY_STRING = "\0"[0..0];

void main() {
    char[64] buf1 = EMPTY_STRING;
}

Note that the following does not:

void main() {
    char[64] buf1 = "\0"[0..0];
}

I use the enum in my code to ensure that empty, static strings are also zero terminated and are non-null. I just noticed this issue in LDC 1.8.0 when porting some c++ code and upgraded to 1.12.0 but the problem remained.
Using Windows 7 on x64, crashing with any configuration of options i tried.
Log:

Wrote crash dump file "%AppData%\Local\Temp\ldc2.exe-10b946.dmp"
0x0000000141765B2E (0x0000000000A05FA0 0x0000000141919740 0x0000000003636F90 0x0000000002602470)
0x000000014010BF8C (0x0000000000000000 0x0000000003639380 0x00000000009FEEA0 0x00000000036393F0)
0x0000000140107AB6 (0x0000000000A05ED0 0x000000014009FCE6 0x00000001419457E0 0x00000000009FF1A0)
0x0000000140107CA1 (0x00000000009FEEF0 0x0000000000A05ED0 0x0000000000008000 0x0000000000000040)
0x000000014008EC62 (0x0000000140024450 0x0000000000000000 0x00000000009FF2F0 0x00000000026023D0)
0x00000001400C073C (0x0000000000B69E30 0x00000000009FF340 0x0000000000000000 0x00000001417AB340)
0x000000014007EC25 (0x0000000141901740 0x000000013FFBC6A6 0x0000000000000000 0x0000000000000000)
0x000000013FF9E86E (0x0000000000000000 0x0000000000B69B54 0x0000000000B6A130 0x0000000000B69B54)
0x000000013FF9F0DD (0x0000000003636E80 0x000000000276FA00 0x0000000000000000 0x000000014193B3B0)
0x000000013FFCA000 (0x00000000009FF680 0x000000013FFD1DD6 0x0000000000A05730 0x0000000140024F4C)
0x000000013FFC872E (0x0000000018000888 0x00000000009FF740 0x00000000009FF740 0x00000000026027A0)
0x00000001400264BA (0x0000000018000888 0x00000000026027A0 0x00000000009FF980 0x0000000000C01E90)
0x00000001401F223E (0x0000000000000001 0x00000000009FFA50 0x0000000000000000 0x0000000000000000)
0x000000013FF71021 (0x0000000000000001 0x0000000000C2D222 0x0000000000000008 0x00000000009FFBD0)
0x000000014014EE5D (0x0000000000000000 0x000000014014EB5B 0x00000001423175C8 0x000000014014EA98)
0x000000014014ED03 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x01D46C9891028D7D)
0x0000000141764734 (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000)
0x00000000772059CD (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000), BaseThreadInitThunk() + 0xD bytes(s)
0x000000007736385D (0x0000000000000000 0x0000000000000000 0x0000000000000000 0x0000000000000000), RtlUserThreadStart() + 0x1D bytes(s)

Dmp file info:


Dump Summary
------------
Dump File:	ldc2.exe-10b946.dmp : C:\Users\Ulki99\AppData\Local\Temp\ldc2.exe-10b946.dmp
Last Write Time:	25.10.2018 21:26:02
Process Name:	ldc2.exe : C:\D\ldc2\bin\ldc2.exe
Process Architecture:	x64
Exception Code:	0xC0000005
Exception Information:	The thread tried to read from or write to a virtual address for which it does not have the appropriate access.
Heap Information:	Not Present

System Information
------------------
OS Version:	6.1.7601
CLR Version(s):	

Modules
-------
Module Name	Module Path	Module Version
-----------	-----------	--------------
ldc2.exe	C:\D\ldc2\bin\ldc2.exe	0.0.0.0
ntdll.dll	C:\Windows\System32\ntdll.dll	6.1.7601.24231
kernel32.dll	C:\Windows\System32\kernel32.dll	6.1.7601.24231
KERNELBASE.dll	C:\Windows\System32\KERNELBASE.dll	6.1.7601.24231
shell32.dll	C:\Windows\System32\shell32.dll	6.1.7601.24234
msvcrt.dll	C:\Windows\System32\msvcrt.dll	7.0.7601.17744
shlwapi.dll	C:\Windows\System32\shlwapi.dll	6.1.7601.17514
gdi32.dll	C:\Windows\System32\gdi32.dll	6.1.7601.24234
user32.dll	C:\Windows\System32\user32.dll	6.1.7601.23594
lpk.dll	C:\Windows\System32\lpk.dll	6.1.7601.24231
usp10.dll	C:\Windows\System32\usp10.dll	1.626.7601.23894
ole32.dll	C:\Windows\System32\ole32.dll	6.1.7601.24168
rpcrt4.dll	C:\Windows\System32\rpcrt4.dll	6.1.7601.24231
advapi32.dll	C:\Windows\System32\advapi32.dll	6.1.7601.24231
sechost.dll	C:\Windows\System32\sechost.dll	6.1.7600.16385
dbghelp.dll	C:\Windows\System32\dbghelp.dll	6.1.7601.17514
ws2_32.dll	C:\Windows\System32\ws2_32.dll	6.1.7601.23451
nsi.dll	C:\Windows\System32\nsi.dll	6.1.7601.23889
imm32.dll	C:\Windows\System32\imm32.dll	6.1.7600.16385
msctf.dll	C:\Windows\System32\msctf.dll	6.1.7601.23915
api-ms-win-core-synch-l1-2-0.DLL	C:\Windows\System32\api-ms-win-core-synch-l1-2-0.DLL	10.0.14393.2247
profapi.dll	C:\Windows\System32\profapi.dll	6.1.7600.16385
cryptsp.dll	C:\Windows\System32\cryptsp.dll	6.1.7601.23471
rsaenh.dll	C:\Windows\System32\rsaenh.dll	6.1.7600.16385
CRYPTBASE.dll	C:\Windows\System32\CRYPTBASE.dll	6.1.7601.24231
powrprof.dll	C:\Windows\System32\powrprof.dll	6.1.7600.16385
setupapi.dll	C:\Windows\System32\setupapi.dll	6.1.7601.17514
cfgmgr32.dll	C:\Windows\System32\cfgmgr32.dll	6.1.7601.17514
oleaut32.dll	C:\Windows\System32\oleaut32.dll	6.1.7601.24117
devobj.dll	C:\Windows\System32\devobj.dll	6.1.7600.16385
@kinke
Copy link
Member

kinke commented Oct 25, 2018

void foo() { char[64] buf1 = "\0"[0..0]; }

I was wondering what that actually produces, and in fact, it's horrible:

@.str = private unnamed_addr constant [1 x i8] zeroinitializer ; [#uses = 1]
...
define void @void onlineapp.foo()() #0 comdat {
  %buf1 = alloca [64 x i8], align 1               ; [#uses = 2, size/byte = 64]
  %1 = bitcast [64 x i8]* %buf1 to i8*            ; [#uses = 1]
  call void @llvm.memcpy.p0i8.p0i8.i64(i8* align 1 %1, i8* align 1 getelementptr inbounds ([1 x i8], [1 x i8]* @.str, i32 0, i32 0), i64 64, i1 false)
  %2 = bitcast [64 x i8]* %buf1 to i8*            ; [#uses = 1]
  %3 = insertvalue { i64, i8* } { i64 64, i8* undef }, i8* %2, 1 ; [#uses = 0]
  ret void
}

What do you actually expect to happen? You're trying to initialize 64 bytes with a 0-length slice, whose underlying payload is a single 0-byte. Do you expect that 0-byte to be copied as first element and the remaining 63 bytes to be left uninitialized? [That'd be char[64] buf1 = void; buf1[0] = 0;.]

@dnadlinger
Copy link
Member

Yep, this seems like invalid code that should be a compiler error at first glance.

@KytoDragon
Copy link
Contributor Author

I am totally fine with this being a compiler error. I was just porting code from c++ where char[32] buf = "" puts a '\0' into the first slot. Removing the initialisation in D (as D auto-initializes all the elements to 0) is easy when you know where the error is.

@kinke
Copy link
Member

kinke commented Oct 25, 2018

Ah, okay. D actually initializes UTF8 chars with 0xFF.

@kinke
Copy link
Member

kinke commented Feb 2, 2019

Filed upstream: https://issues.dlang.org/show_bug.cgi?id=19639

@kinke
Copy link
Member

kinke commented Feb 5, 2019

The segfault was fixed by dlang/dmd#9321.

I filed another issue wrt. void foo() { char[64] buf1 = "\0"[0..0]; }, which 'works' for LDC (reading beyond string literal), while DMD yields a runtime error: https://issues.dlang.org/show_bug.cgi?id=19651

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants