[llvm-bugs] [Bug 48071] New: Segfault in MarkLive<ELFT>::enqueue, due to MergeInputSection::getSectionPiece failure

via llvm-bugs llvm-bugs at lists.llvm.org
Wed Nov 4 05:31:45 PST 2020


https://bugs.llvm.org/show_bug.cgi?id=48071

            Bug ID: 48071
           Summary: Segfault in MarkLive<ELFT>::enqueue, due to
                    MergeInputSection::getSectionPiece failure
           Product: lld
           Version: unspecified
          Hardware: PC
                OS: All
            Status: NEW
          Severity: normal
          Priority: P
         Component: ELF
          Assignee: unassignedbugs at nondot.org
          Reporter: dimitry at andric.com
                CC: llvm-bugs at lists.llvm.org, smithp352 at googlemail.com

In https://bugs.freebsd.org/250783 Nick Venenga reports an lld 11.0.0 segfault
when building the 'maturin' Python package. The reproduction tarball was
uploaded to <https://files.nickv.me/bug250783.tar.xz>.

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>
>::enqueue (this=0x7fffffffd230, sec=0x55555d570f40, offset=0) at
/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>
>::enqueue (this=0x7fffffffd230, sec=0x55555d570f40, offset=0) at
/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>
>::resolveReloc<llvm::object::Elf_Rel_Impl<llvm::object::ELFType<(llvm::support::endianness)1,
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>
>::mark (this=0x7fffffffd230) at
/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>
>::run (this=0x7fffffffd230) at
/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?

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20201104/62574062/attachment-0001.html>


More information about the llvm-bugs mailing list