D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 19639 - Initializing static array with slice enum of different length crashes the compiler
Summary: Initializing static array with slice enum of different length crashes the com...
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P1 regression
Assignee: No Owner
URL:
Keywords: ice-on-valid-code
Depends on:
Blocks:
 
Reported: 2019-02-02 20:35 UTC by kinke
Modified: 2019-02-05 19:54 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description kinke 2019-02-02 20:35:47 UTC
```
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 Neia Neutuladh 2019-02-02 21:06:35 UTC
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 Neia Neutuladh 2019-02-02 21:43:51 UTC
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: 楨錀缳Ჰ鏌缳 ɱ荀Ű
Comment 3 Neia Neutuladh 2019-02-02 22:44:41 UTC
https://github.com/dlang/dmd/pull/9317 fixes this, but I won't be able to pursue this further, and there are associated breakages.
Comment 4 kinke 2019-02-05 19:54:37 UTC
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.