From: George Rimar Date: Tue, 23 Jul 2019 11:37:14 +0000 (+0000) Subject: [Object/ELF.h] - Improve testing of the fields in ELFFile::sections(). X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bf24a666304f32d70e243d98fe17f096b442e591;p=llvm [Object/ELF.h] - Improve testing of the fields in ELFFile::sections(). 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 --- diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index cf8e4529bad..83823af2fc8 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -513,15 +513,22 @@ Expected ELFFile::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/include/llvm/ObjectYAML/ELFYAML.h b/include/llvm/ObjectYAML/ELFYAML.h index f03c4054c0a..89c0c5827f9 100644 --- a/include/llvm/ObjectYAML/ELFYAML.h +++ b/include/llvm/ObjectYAML/ELFYAML.h @@ -77,7 +77,7 @@ struct FileHeader { llvm::yaml::Hex64 Entry; Optional SHEntSize; - Optional SHOffset; + Optional SHOffset; Optional SHNum; Optional SHStrNdx; }; diff --git a/test/Object/invalid.test b/test/Object/invalid.test index 5723c4aef33..77e6d0bddd0 100644 --- a/test/Object/invalid.test +++ b/test/Object/invalid.test @@ -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 diff --git a/tools/yaml2obj/yaml2elf.cpp b/tools/yaml2obj/yaml2elf.cpp index f3a8a91861d..c6be508a64a 100644 --- a/tools/yaml2obj/yaml2elf.cpp +++ b/tools/yaml2obj/yaml2elf.cpp @@ -244,7 +244,7 @@ void ELFState::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;