]> granicus.if.org Git - llvm/commitdiff
[Object/ELF.h] - Improve testing of the fields in ELFFile<ELFT>::sections().
authorGeorge Rimar <grimar@accesssoftek.com>
Tue, 23 Jul 2019 11:37:14 +0000 (11:37 +0000)
committerGeorge Rimar <grimar@accesssoftek.com>
Tue, 23 Jul 2019 11:37:14 +0000 (11:37 +0000)
This eliminates a one error untested and
also introduces a error for one more possible case
which lead to crash previously.

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

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@366796 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Object/ELF.h
include/llvm/ObjectYAML/ELFYAML.h
test/Object/invalid.test
tools/yaml2obj/yaml2elf.cpp

index cf8e4529bad96557ec56a55ae81c17cd1a4b5e77..83823af2fc8ad26b6387a95c840eef3e96ff9d6d 100644 (file)
@@ -513,15 +513,22 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
     NumSections = First->sh_size;
 
   if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
-    // TODO: this error is untested.
-    return createError("section table goes past the end of file");
+    return createError("invalid number of sections specified in the NULL "
+                       "section's sh_size field (" +
+                       Twine(NumSections) + ")");
 
   const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);
+  if (SectionTableOffset + SectionTableSize < SectionTableOffset)
+    return createError(
+        "invalid section header table offset (e_shoff = 0x" +
+        Twine::utohexstr(SectionTableOffset) +
+        ") or invalid number of sections specified in the first section "
+        "header's sh_size field (0x" +
+        Twine::utohexstr(NumSections) + ")");
 
   // Section table goes past end of file!
   if (SectionTableOffset + SectionTableSize > FileSize)
     return createError("section table goes past the end of file");
-
   return makeArrayRef(First, NumSections);
 }
 
index f03c4054c0ae6188ad926cdff1449ddc6c2685e8..89c0c5827f952201d08be7e66bab267a0f1be289 100644 (file)
@@ -77,7 +77,7 @@ struct FileHeader {
   llvm::yaml::Hex64 Entry;
 
   Optional<llvm::yaml::Hex16> SHEntSize;
-  Optional<llvm::yaml::Hex16> SHOffset;
+  Optional<llvm::yaml::Hex64> SHOffset;
   Optional<llvm::yaml::Hex16> SHNum;
   Optional<llvm::yaml::Hex16> SHStrNdx;
 };
index 5723c4aef338729d64d98f3a8290d753f96ba9d1..77e6d0bddd0b85be2014e8c55cc075812a1dcf18 100644 (file)
@@ -552,3 +552,58 @@ FileHeader:
 Sections:
   - Name: .foo
     Type: SHT_PROGBITS
+
+## We report an error if the number of sections stored in sh_size
+## is greater than UINT64_MAX / sizeof(Elf_Shdr) == 288230376151711743.
+## Here we check that do not crash on a border value.
+
+# RUN: yaml2obj --docnum=26 %s -o %t26
+# RUN: not llvm-readobj -h %t26 2>&1 | FileCheck -DFILE=%t26 --check-prefix=INVALID-SEC-NUM1 %s
+
+# INVALID-SEC-NUM1: error: '[[FILE]]': invalid section header table offset (e_shoff = 0x40) or invalid number of sections specified in the first section header's sh_size field (0x3ffffffffffffff)
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+  SHNum:   0x0
+Sections:
+  - Type: SHT_NULL
+    Size: 288230376151711743
+
+## See above, but now we test the UINT64_MAX / sizeof(Elf_Shdr) value.
+## The error is slightly different in this case.
+
+# RUN: yaml2obj --docnum=27 %s -o %t27
+# RUN: not llvm-readobj -h %t27 2>&1 | FileCheck -DFILE=%t27 --check-prefix=INVALID-SEC-NUM2 %s
+
+# INVALID-SEC-NUM2: error: '[[FILE]]': invalid number of sections specified in the NULL section's sh_size field (288230376151711744)
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+  SHNum:   0x0
+Sections:
+  - Type: SHT_NULL
+    Size: 288230376151711744
+
+## Check the case when SHOffset is too large, but SHNum is not. SHOffset + SHNum overflows the uint64 type.
+
+# RUN: yaml2obj --docnum=28 %s -o %t28
+# RUN: not llvm-readobj -h %t28 2>&1 | FileCheck -DFILE=%t28 --check-prefix=INVALID-SEC-NUM3 %s
+
+# INVALID-SEC-NUM3: error: '[[FILE]]': invalid section header table offset (e_shoff = 0xffffffffffffffff) or invalid number of sections specified in the first section header's sh_size field (0x1)
+
+--- !ELF
+FileHeader:
+  Class:    ELFCLASS64
+  Data:     ELFDATA2LSB
+  Type:     ET_REL
+  Machine:  EM_X86_64
+  SHOffset: 0xffffffffffffffff
+  SHNum:    0x1
index f3a8a91861d4228875b83231a5e949de2e29d0ca..c6be508a64ae9db6667cd6ac7eb84d4410cba218 100644 (file)
@@ -244,7 +244,7 @@ void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) {
   // Immediately following the ELF header and program headers.
   Header.e_shoff =
       Doc.Header.SHOffset
-          ? (uint16_t)*Doc.Header.SHOffset
+          ? (typename ELFT::uint)(*Doc.Header.SHOffset)
           : sizeof(Header) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size();
   Header.e_shnum =
       Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : SN2I.size() + 1;