<html>
<head>
<base href="https://bugs.llvm.org/">
</head>
<body><table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Bug ID</th>
<td><a class="bz_bug_link
bz_status_NEW "
title="NEW - Segfault in MarkLive<ELFT>::enqueue, due to MergeInputSection::getSectionPiece failure"
href="https://bugs.llvm.org/show_bug.cgi?id=48071">48071</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>Segfault in MarkLive<ELFT>::enqueue, due to MergeInputSection::getSectionPiece failure
</td>
</tr>
<tr>
<th>Product</th>
<td>lld
</td>
</tr>
<tr>
<th>Version</th>
<td>unspecified
</td>
</tr>
<tr>
<th>Hardware</th>
<td>PC
</td>
</tr>
<tr>
<th>OS</th>
<td>All
</td>
</tr>
<tr>
<th>Status</th>
<td>NEW
</td>
</tr>
<tr>
<th>Severity</th>
<td>normal
</td>
</tr>
<tr>
<th>Priority</th>
<td>P
</td>
</tr>
<tr>
<th>Component</th>
<td>ELF
</td>
</tr>
<tr>
<th>Assignee</th>
<td>unassignedbugs@nondot.org
</td>
</tr>
<tr>
<th>Reporter</th>
<td>dimitry@andric.com
</td>
</tr>
<tr>
<th>CC</th>
<td>llvm-bugs@lists.llvm.org, smithp352@googlemail.com
</td>
</tr></table>
<p>
<div>
<pre>In <a href="https://bugs.freebsd.org/250783">https://bugs.freebsd.org/250783</a> Nick Venenga reports an lld 11.0.0 segfault
when building the 'maturin' Python package. The reproduction tarball was
uploaded to <<a href="https://files.nickv.me/bug250783.tar.xz">https://files.nickv.me/bug250783.tar.xz</a>>.
The segfault also occurs with llvmorg-12-init-10746-g351c10cc721 (as of
2020-11-04):
Starting program:
/home/dim/obj/llvm-llvmorg-12-init-10746-g351c10cc721-linux5-x86_64-ninja-gcc-dbg-1/bin/ld.lld
@response.txt
...
Thread 1 "ld.lld" received signal SIGSEGV, Segmentation fault.
(anonymous
namespace)::MarkLive<llvm::object::ELFType<(llvm::support::endianness)1, true>
<span class="quote">>::enqueue (this=0x7fffffffd230, sec=0x55555d570f40, offset=0) at</span >
/home/dim/src/llvm/llvm-project/lld/ELF/MarkLive.cpp:194
194 ms->getSectionPiece(offset)->live = true;
(gdb) bt
#0 (anonymous
namespace)::MarkLive<llvm::object::ELFType<(llvm::support::endianness)1, true>
<span class="quote">>::enqueue (this=0x7fffffffd230, sec=0x55555d570f40, offset=0) at</span >
/home/dim/src/llvm/llvm-project/lld/ELF/MarkLive.cpp:194
#1 0x000055555750bbcf in (anonymous
namespace)::MarkLive<llvm::object::ELFType<(llvm::support::endianness)1, true>
<span class="quote">>::resolveReloc<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1,</span >
true>, true> const> (this=0x7fffffffd230, sec=..., rel=..., isLSDA=false) at
/home/dim/src/llvm/llvm-project/lld/ELF/MarkLive.cpp:108
#2 0x000055555750a53a in (anonymous
namespace)::MarkLive<llvm::object::ELFType<(llvm::support::endianness)1, true>
<span class="quote">>::mark (this=0x7fffffffd230) at</span >
/home/dim/src/llvm/llvm-project/lld/ELF/MarkLive.cpp:279
#3 0x00005555575087c6 in (anonymous
namespace)::MarkLive<llvm::object::ELFType<(llvm::support::endianness)1, true>
<span class="quote">>::run (this=0x7fffffffd230) at</span >
/home/dim/src/llvm/llvm-project/lld/ELF/MarkLive.cpp:269
#4 0x000055555750d857 in
lld::elf::markLive<llvm::object::ELFType<(llvm::support::endianness)1, true> >
() at /home/dim/src/llvm/llvm-project/lld/ELF/MarkLive.cpp:382
#5 0x000055555740e3fe in
lld::elf::LinkerDriver::link<llvm::object::ELFType<(llvm::support::endianness)1,
true> > (this=0x55555d4c6410, args=...) at
/home/dim/src/llvm/llvm-project/lld/ELF/Driver.cpp:2211
#6 0x00005555573f59cf in lld::elf::LinkerDriver::main (this=0x55555d4c6410,
argsArr=...) at /home/dim/src/llvm/llvm-project/lld/ELF/Driver.cpp:557
#7 0x00005555573f199a in lld::elf::link (args=..., canExitEarly=true,
stdoutOS=..., stderrOS=...) at
/home/dim/src/llvm/llvm-project/lld/ELF/Driver.cpp:120
#8 0x0000555557174d59 in lldMain (argc=2, argv=0x7fffffffe398, stdoutOS=...,
stderrOS=..., exitEarly=true) at
/home/dim/src/llvm/llvm-project/lld/tools/lld/lld.cpp:153
#9 0x00005555571751bb in main (argc=2, argv=0x7fffffffe398) at
/home/dim/src/llvm/llvm-project/lld/tools/lld/lld.cpp:211
It turns out that MergeInputSection::getSectionPiece() returns garbage:
1410 SectionPiece *MergeInputSection::getSectionPiece(uint64_t offset) {
1411 if (this->data().size() <= offset)
1412 fatal(toString(this) + ": offset is outside the section");
1413
1414 // If Offset is not at beginning of a section piece, it is not in the
map.
1415 // In that case we need to do a binary search of the original
section piece vector.
1416 auto it = partition_point(
1417 pieces, [=](SectionPiece p) { return p.inputOff <= offset; });
1418 return &it[-1];
1419 }
In this case partition_point() actually returns pieces.begin(), so it[-1] is an
invalid iterator. This is really undefined behavior, and in my opinion an
assert should be added in this function to ensure this cannot happen.
That said, it looks like partition_point "Requires that [the predicate] is
always true below some limit, and always false above it", and that assumption
may have been violated. E.g, here p.inputOff might always be larger than
offset?</pre>
</div>
</p>
<hr>
<span>You are receiving this mail because:</span>
<ul>
<li>You are on the CC list for the bug.</li>
</ul>
</body>
</html>