Index: include/llvm/Object/ELF.h =================================================================== --- include/llvm/Object/ELF.h +++ include/llvm/Object/ELF.h @@ -513,15 +513,22 @@ 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 = " + + Twine::utohexstr(SectionTableOffset) + + ") or invalid number of sections specified in the first section " + "header's sh_size field (" + + 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: include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- include/llvm/ObjectYAML/ELFYAML.h +++ include/llvm/ObjectYAML/ELFYAML.h @@ -77,7 +77,7 @@ llvm::yaml::Hex64 Entry; Optional SHEntSize; - Optional SHOffset; + Optional SHOffset; Optional SHNum; Optional SHStrNdx; }; Index: test/Object/invalid.test =================================================================== --- test/Object/invalid.test +++ test/Object/invalid.test @@ -552,3 +552,58 @@ 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 = 40) or invalid number of sections specified in the first section header's sh_size field (3ffffffffffffff) + +--- !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 = ffffffffffffffff) or invalid number of sections specified in the first section header's sh_size field (1) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 + SHOffset: 0xffffffffffffffff + SHNum: 0x1 Index: tools/yaml2obj/yaml2elf.cpp =================================================================== --- tools/yaml2obj/yaml2elf.cpp +++ tools/yaml2obj/yaml2elf.cpp @@ -217,7 +217,7 @@ // 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;