The following program segfaults with dmd v2.079.0 when compiled with no arguments in x86_64:
```
import std.bitmanip;
void main(string[] args) {
auto barray = BitArray();
ulong evilVal = 2534886795;
barray.length = evilVal + 1;
barray[evilVal];
}
```
The segfault happens there:
╭ (fcn) sym._D4core5bitop2btFNaNbNixPmmZi 13
│ sym._D4core5bitop2btFNaNbNixPmmZi ();
│ 0x5558709cde6c 55 push rbp
│ 0x5558709cde6d 488bec mov rbp, rsp
| ;-- rip:
│ 0x5558709cde70 0fa33e bt dword [rsi], edi
│ 0x5558709cde73 19c0 sbb eax, eax
│ 0x5558709cde75 f7d8 neg eax
│ 0x5558709cde77 5d pop rbp
╰ 0x5558709cde78 c3 ret
0x5558709cde79 0000 add byte [rax], al
0x5558709cde7b ~ 005548 add byte [rbp + 0x48], dl
At that point we have:
rsi = 0x7f40163e2010 -> our BitArray
rdi = 0x97174d8b -> "evilVal"
A look at /proc/*/maps shows that the call falls into that section:
0x00007f40163e2000 # 0x00007f4032928000 - usr 453.3M s -rw- unk1 unk1
IIUC this is what was allocated for our BitArray. However this isn't enough as 0x00007f4032928000 - 0x00007f40163e2000 < 2534886795.
Therefore my understanding is that not enough memory was allocated to hold the BitArray even though we specified a length strictly greater than the index we are accessing.
(In reply to Cédric Picard from comment #0)
> │ 0x5558709cde70 0fa33e bt dword [rsi], edi
>
>
> At that point we have:
> rsi = 0x7f40163e2010 -> our BitArray
> rdi = 0x97174d8b -> "evilVal"
This is a codegen bug. It should be rdi in the bt instruction, not edi.
It's hard to find information on this, but this page says that the bt instruction interprets the offset as signed: <http://faydoc.tripod.com/cpu/bt.htm>. So rdi = 0x97174d8b becomes edi = -1760080501. That's not intended, of course.
I've filed a new issue for the dmd bug: issue 18730. When that one gets fixed, this one can be closed as a duplicate. Or thise one can be fixed by working around the dmd bug in the BitArray code.
> A look at /proc/*/maps shows that the call falls into that section:
>
> 0x00007f40163e2000 # 0x00007f4032928000 - usr 453.3M s -rw- unk1 unk1
>
> IIUC this is what was allocated for our BitArray. However this isn't enough
> as 0x00007f4032928000 - 0x00007f40163e2000 < 2534886795.
You're comparing bytes to bits there. 2534886795 is the number of bits in the array. That means, it needs ceil(2534886795 / 8) = 316860850 bytes. And that's less than 0x00007f4032928000 - 0x00007f40163e2000.
Comment #3 by cpicard — 2018-04-05T15:55:03Z
Thanks a lot, your interpretation makes sense.
Comment #4 by ag0aep6g — 2018-04-30T17:17:54Z
(In reply to ag0aep6g from comment #2)
> I've filed a new issue for the dmd bug: issue 18730. When that one gets
> fixed, this one can be closed as a duplicate.
18730 has been fixed. Closing this one as a duplicate.
*** This issue has been marked as a duplicate of issue 18730 ***