diff options
-rw-r--r-- | llvm/include/llvm/Object/ELF.h | 16 | ||||
-rw-r--r-- | llvm/include/llvm/ObjectYAML/ELFYAML.h | 2 | ||||
-rw-r--r-- | llvm/test/Object/invalid.test | 54 | ||||
-rw-r--r-- | llvm/tools/yaml2obj/yaml2elf.cpp | 2 |
4 files changed, 68 insertions, 6 deletions
diff --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h index cf8e4529bad..5638ea73935 100644 --- a/llvm/include/llvm/Object/ELF.h +++ b/llvm/include/llvm/Object/ELF.h @@ -495,7 +495,8 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const { Twine(getHeader()->e_shentsize)); const uint64_t FileSize = Buf.size(); - if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize) + if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize || + SectionTableOffset + (uintX_t)sizeof(Elf_Shdr) < SectionTableOffset) return createError( "section header table goes past the end of the file: e_shoff = 0x" + Twine::utohexstr(SectionTableOffset)); @@ -513,15 +514,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); } diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h index f03c4054c0a..89c0c5827f9 100644 --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -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; }; diff --git a/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test index 5723c4aef33..5fe107ff268 100644 --- a/llvm/test/Object/invalid.test +++ b/llvm/test/Object/invalid.test @@ -552,3 +552,57 @@ 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. SHOffset + sizeof(Elf_Shdr) 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]]': section header table goes past the end of the file: e_shoff = 0xffffffffffffffff + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + SHOffset: 0xffffffffffffffff diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp index f3a8a91861d..c6be508a64a 100644 --- a/llvm/tools/yaml2obj/yaml2elf.cpp +++ b/llvm/tools/yaml2obj/yaml2elf.cpp @@ -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; |