[ELF] - Fix crash relative to SHF_LINK_ORDER sections.
authorGeorge Rimar <grimar@accesssoftek.com>
Thu, 8 Mar 2018 15:06:58 +0000 (15:06 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Thu, 8 Mar 2018 15:06:58 +0000 (15:06 +0000)
Our code assumes all input sections in an output SHF_LINK_ORDER
section has SHF_LINK_ORDER flag. We do not check that and that can cause a crash.

That happens because we call
std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);,
where compareByFilePosition predicate does not expect to see
null when calls getLinkOrderDep.

The same might happen when sections refer to non-regular sections.
Test cases demonstrate the issues, patch fixes them.

Differential revision: https://reviews.llvm.org/D44193

llvm-svn: 327006

lld/ELF/InputFiles.cpp
lld/ELF/InputSection.cpp
lld/ELF/OutputSections.cpp
lld/test/ELF/section-metadata-err.s
lld/test/ELF/section-metadata-err2.s [new file with mode: 0644]
lld/test/ELF/section-metadata-err3.s [new file with mode: 0644]

index 9028ea5..8993b23 100644 (file)
@@ -431,8 +431,15 @@ void ObjFile<ELFT>::initializeSections(
       if (Sec.sh_link >= this->Sections.size())
         fatal(toString(this) +
               ": invalid sh_link index: " + Twine(Sec.sh_link));
-      this->Sections[Sec.sh_link]->DependentSections.push_back(
-          cast<InputSection>(this->Sections[I]));
+
+      InputSectionBase *LinkSec = this->Sections[Sec.sh_link];
+      InputSection *IS = cast<InputSection>(this->Sections[I]);
+      LinkSec->DependentSections.push_back(IS);
+      if (!isa<InputSection>(LinkSec))
+        error("a section " + IS->Name +
+              " with SHF_LINK_ORDER should not refer a non-regular "
+              "section: " +
+              toString(LinkSec));
     }
   }
 }
index f7a757e..713a781 100644 (file)
@@ -206,15 +206,9 @@ void InputSectionBase::maybeDecompress() {
 }
 
 InputSection *InputSectionBase::getLinkOrderDep() const {
-  if ((Flags & SHF_LINK_ORDER) && Link != 0) {
-    InputSectionBase *L = File->getSections()[Link];
-    if (auto *IS = dyn_cast<InputSection>(L))
-      return IS;
-    error("a section with SHF_LINK_ORDER should not refer a non-regular "
-          "section: " +
-          toString(L));
-  }
-  return nullptr;
+  assert(Link);
+  assert(Flags & SHF_LINK_ORDER);
+  return cast<InputSection>(File->getSections()[Link]);
 }
 
 // Returns a source location string. Used to construct an error message.
index 8f29b29..1d03c56 100644 (file)
@@ -98,7 +98,8 @@ void OutputSection::addSection(InputSection *IS) {
     Flags = IS->Flags;
   } else {
     // Otherwise, check if new type or flags are compatible with existing ones.
-    if ((Flags & (SHF_ALLOC | SHF_TLS)) != (IS->Flags & (SHF_ALLOC | SHF_TLS)))
+    unsigned Mask = SHF_ALLOC | SHF_TLS | SHF_LINK_ORDER;
+    if ((Flags & Mask) != (IS->Flags & Mask))
       error("incompatible section flags for " + Name + "\n>>> " + toString(IS) +
             ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name +
             ": 0x" + utohexstr(Flags));
index 1bcbedf..ba102be 100644 (file)
@@ -3,7 +3,7 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
 # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
 
-# CHECK: error: a section with SHF_LINK_ORDER should not refer a non-regular section: {{.*}}section-metadata-err.s.tmp.o:(.foo)
+# CHECK: error: a section .bar with SHF_LINK_ORDER should not refer a non-regular section: {{.*}}section-metadata-err.s.tmp.o:(.foo)
 
 .global _start
 _start:
@@ -12,4 +12,4 @@ _start:
 .section .foo,"aM",@progbits,8
 .quad 0
 
-.section bar,"ao",@progbits,.foo
+.section .bar,"ao",@progbits,.foo
diff --git a/lld/test/ELF/section-metadata-err2.s b/lld/test/ELF/section-metadata-err2.s
new file mode 100644 (file)
index 0000000..b2b611f
--- /dev/null
@@ -0,0 +1,17 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+## Check we do not crash and report proper errors.
+# CHECK: error: a section .bar with SHF_LINK_ORDER should not refer a non-regular section: {{.*}}section-metadata-err2.s.tmp.o:(.foo)
+# CHECK: error: a section .bar with SHF_LINK_ORDER should not refer a non-regular section: {{.*}}section-metadata-err2.s.tmp.o:(.foo)
+
+.section .foo,"aM",@progbits,8
+.quad 0
+
+.section .bar,"ao",@progbits,.foo,unique,1
+.quad 0
+
+.section .bar,"ao",@progbits,.foo,unique,2
+.quad 1
diff --git a/lld/test/ELF/section-metadata-err3.s b/lld/test/ELF/section-metadata-err3.s
new file mode 100644 (file)
index 0000000..36666bf
--- /dev/null
@@ -0,0 +1,17 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
+
+# CHECK:      error: incompatible section flags for .bar
+# CHECK-NEXT: >>> {{.*}}section-metadata-err3.s.tmp.o:(.bar): 0x2
+# CHECK-NEXT: >>> output section .bar: 0x82
+
+.section .foo,"a",@progbits
+.quad 0
+
+.section .bar,"ao",@progbits,.foo,unique,1
+.quad 0
+
+.section .bar,"a",@progbits,unique,2
+.quad 1