Bug 19639 – Initializing static array with slice enum of different length crashes the compiler
Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2019-02-02T20:35:47Z
Last change time
2019-02-05T19:54:37Z
Keywords
ice-on-valid-code
Assigned to
No Owner
Creator
kinke
Comments
Comment #0 by kinke — 2019-02-02T20:35:47Z
```
enum EMPTY_STRING = "\0"[0..0];
void main() { char[64] buf = EMPTY_STRING; }
```
According to https://run.dlang.io/is/zQsYSf, this results in runtime errors for v2.060-65 ('array length mismatch'), compiles successfully (!) for v2.066-70, and crashes the compiler since 2.071.
Note that `void main() { char[64] buf = "\0"[0..0]; }` results in runtime errors for all tested versions.
A non-empty slice `enum EMPTY_STRING = "\0"[0..1]` compiles successfully (!) since v2.066, while previous versions and `void main() { char[64] buf = "\0"[0..1]; }` yield runtime errors.
It's not just initializations, but assignments too (`void main() { char[64] buf; buf = EMPTY_STRING; }`).
Originally posted here: https://github.com/ldc-developers/ldc/issues/2882
Comment #1 by dhasenan — 2019-02-02T21:06:35Z
It's a segfault, to be more specific.
Stacktrace:
__memmove_sse2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:332
332 ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S: Dosiero aŭ dosierujo ne ekzistas.
(gdb) bt
#0 __memmove_sse2_unaligned_erms () at ../sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S:332
#1 0x00005555557d5621 in castTo::CastTo::visit(StringExp*) (this=0x7fffffffb230, e=0x555555e12100) at dmd/dcast.d:1863
#2 0x0000555555843096 in StringExp::accept(Visitor*) (this=0x555555e12100, v=0x7fffffffb230) at dmd/expression.d:2587
#3 0x00005555557d45ff in _D3dmd5dcast6castToFCQt10expression10ExpressionPSQBv6dscope5ScopeCQCm5mtype4TypeZQCj (t=0x7ffff6b01790,
sc=0x7ffff682d620, e=0x555555e12100) at dmd/dcast.d:2574
#4 0x000055555583f3c9 in Expression::castTo(Scope*, Type*) (this=0x555555e12100, sc=0x7ffff682d620, t=0x7ffff6b01790) at dmd/expression.d:923
#5 0x00005555557d1786 in implicitCastTo::ImplicitCastTo::visit(Expression*) (this=0x7fffffffb3e0, e=0x555555e12100) at dmd/dcast.d:124
#6 0x00005555557d18b9 in implicitCastTo::ImplicitCastTo::visit(StringExp*) (this=0x7fffffffb3e0, e=0x555555e12100) at dmd/dcast.d:157
#7 0x0000555555843096 in StringExp::accept(Visitor*) (this=0x555555e12100, v=0x7fffffffb3e0) at dmd/expression.d:2587
I wasn't able to get this to work with other types of arrays. Changing from "\0" to [cast(immutable)'\0'] also made the problem go away.
Comment #2 by dhasenan — 2019-02-02T21:43:51Z
For some reason, this is doing a reinterpret cast.
It isn't documented that you can do this kind of cast into a static array. It's only mentioned for dynamic arrays to dynamic arrays.
The examples in the compiler source code (is that where we're keeping the spec these days?) explicitly involve not keeping the same length.
Similar example:
---
void main()
{
writeln(cast(wchar[64])"hi"c);
}
---
Expected output: some sort of error about "hi" not being long enough to fill a wchar[64].
Actual output: 楨錀缳Ჰ鏌缳 ɱ荀Ű
This is apparently valid code since v2.066, as is `char[64] = "abc"`. - https://github.com/dlang/dmd/pull/9321 fixes the segfault and a read-beyond-buffer bug.