Comment #0 by thomas.bockman — 2020-12-29T09:04:05Z
This fails on recent dmd versions with -debug:
/////////////////////////////////////////////////////////////////////////
module app;
struct Stuff {
size_t capacity;
size_t[1] items;
void grow() {
const oldCapacity = capacity;
items.ptr[0 .. oldCapacity] = items.ptr[0 .. oldCapacity];
items.ptr[oldCapacity .. 1] = 0; // Segmentation fault (code -11)
}
}
void main() {
Stuff stuff;
stuff.grow();
}
////////////////////////////////////////////////////////////////////////
run.dlang.io's "All dmd compilers (2.060 - latest)" mode claims the problem started in 2.094.1:
Up to 2.093.1: Success and no output
Since 2.094.1: Failure with output: Error: program killed by signal 11
Comment #1 by thomas.bockman — 2020-12-29T09:05:58Z
Note that it works if the second slice assignment is replaced with an equivalent manual loop.
Comment #2 by razvan.nitu1305 — 2021-02-01T16:32:07Z
This is weird. I cannot reproduce locally with git master. Running on run.dlang.io does indeed seem to produce the segfault, however, if I select dmd, dmd-beta, dmd-nightly the issue does not occur. Is it possible that this issue has been fixed?
Comment #3 by b2.temp — 2021-02-02T10:03:03Z
Possibly caused by https://github.com/dlang/dmd/pull/11427.
Based on this slightly modified TC:
---
struct Stuff {
size_t c; // declare after items and not crash !
ubyte[1] items;
}
void grow(ref Stuff stuff) {
with (stuff)
{
const oldCapacity = c;
items.ptr[0..oldCapacity] = items.ptr[0..0]; // use literal 0 instead of
items.ptr[0] = 0; // oldcapacity and no crash !
}
}
void main() {
Stuff stuff;
grow(stuff);
}
---
before (2.092):
---
_D7example4growFKSQq5StuffZv:
push RBP
mov RBP,RSP
sub RSP,020h
mov -8[RBP],RDI
mov RAX,-8[RBP]
mov -018h[RBP],RAX
mov -018h[RBP],RAX
mov RCX,[RAX]
mov -010h[RBP],RCX
mov RDX,-010h[RBP]
lea RSI,8[RAX]
mov RDI,RSI
mov -020h[RBP],RSI
call memcpy@PLT32 ; memcpy
mov RAX,-020h[RBP]
mov byte ptr [RAX],0
leave
ret
---
cg after (2.084.2):
_D7example4growFKSQq5StuffZv:
push RBP
mov RBP,RSP
sub RSP,020h
mov -8[RBP],RDI
mov RAX,-8[RBP]
mov -018h[RBP],RAX
mov -018h[RBP],RAX
mov RCX,[RAX]
mov -010h[RBP],RCX
lea RSI,8[RAX]
mov RCX,-010h[RBP]
mov RDI,RSI
test RCX,RCX
je $+7h ; debug, break here, set ZF to 0 and no crash !
mov -020h[RBP],RSI ; b/c then the address that will end up in RAX is valid
rep
movsb
mov RAX,-020h[RBP]
mov byte ptr [RAX],0 ; by default here RAX is null, crash
leave
ret
add [RAX],AL
---
I think that the jump is generated here :
https://github.com/dlang/dmd/pull/11427/commits/73ee0d06f2e1fb462c2022089266a15591d226ae#diff-db782f03853977be318903ca0db5f79a34511b2b148fdc4d7399cff85f28b358R3929
Comment #4 by bugzilla — 2021-02-03T09:20:49Z
Ah, I see the problem. Line 3932 is in the wrong place.