Bug 18717 – Segfault in BitManip

Status
RESOLVED
Resolution
DUPLICATE
Severity
normal
Priority
P1
Component
phobos
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2018-04-03T18:53:23Z
Last change time
2018-04-30T17:17:54Z
Assigned to
No Owner
Creator
Cédric Picard
See also
https://issues.dlang.org/show_bug.cgi?id=18730

Comments

Comment #0 by cpicard — 2018-04-03T18:53:23Z
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.
Comment #1 by cpicard — 2018-04-03T18:54:58Z
Forgot to mention that this may be related to https://issues.dlang.org/show_bug.cgi?id=12458 although I do not the issues are the same.
Comment #2 by ag0aep6g — 2018-04-04T23:54:17Z
(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 ***