forked from OSchip/llvm-project
Recommit rr366796 "[Object/ELF.h] - Improve testing of the fields in ELFFile<ELFT>::sections()."
With a fix of the issue found by UBSan. Original commit message: 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 llvm-svn: 366886
This commit is contained in:
parent
b9d96ceca0
commit
ec10d5c6c1
|
@ -495,7 +495,8 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
|
||||||
Twine(getHeader()->e_shentsize));
|
Twine(getHeader()->e_shentsize));
|
||||||
|
|
||||||
const uint64_t FileSize = Buf.size();
|
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(
|
return createError(
|
||||||
"section header table goes past the end of the file: e_shoff = 0x" +
|
"section header table goes past the end of the file: e_shoff = 0x" +
|
||||||
Twine::utohexstr(SectionTableOffset));
|
Twine::utohexstr(SectionTableOffset));
|
||||||
|
@ -513,15 +514,22 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
|
||||||
NumSections = First->sh_size;
|
NumSections = First->sh_size;
|
||||||
|
|
||||||
if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
|
if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
|
||||||
// TODO: this error is untested.
|
return createError("invalid number of sections specified in the NULL "
|
||||||
return createError("section table goes past the end of file");
|
"section's sh_size field (" +
|
||||||
|
Twine(NumSections) + ")");
|
||||||
|
|
||||||
const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);
|
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!
|
// Section table goes past end of file!
|
||||||
if (SectionTableOffset + SectionTableSize > FileSize)
|
if (SectionTableOffset + SectionTableSize > FileSize)
|
||||||
return createError("section table goes past the end of file");
|
return createError("section table goes past the end of file");
|
||||||
|
|
||||||
return makeArrayRef(First, NumSections);
|
return makeArrayRef(First, NumSections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ struct FileHeader {
|
||||||
llvm::yaml::Hex64 Entry;
|
llvm::yaml::Hex64 Entry;
|
||||||
|
|
||||||
Optional<llvm::yaml::Hex16> SHEntSize;
|
Optional<llvm::yaml::Hex16> SHEntSize;
|
||||||
Optional<llvm::yaml::Hex16> SHOffset;
|
Optional<llvm::yaml::Hex64> SHOffset;
|
||||||
Optional<llvm::yaml::Hex16> SHNum;
|
Optional<llvm::yaml::Hex16> SHNum;
|
||||||
Optional<llvm::yaml::Hex16> SHStrNdx;
|
Optional<llvm::yaml::Hex16> SHStrNdx;
|
||||||
};
|
};
|
||||||
|
|
|
@ -552,3 +552,57 @@ FileHeader:
|
||||||
Sections:
|
Sections:
|
||||||
- Name: .foo
|
- Name: .foo
|
||||||
Type: SHT_PROGBITS
|
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
|
||||||
|
|
|
@ -244,7 +244,7 @@ void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) {
|
||||||
// Immediately following the ELF header and program headers.
|
// Immediately following the ELF header and program headers.
|
||||||
Header.e_shoff =
|
Header.e_shoff =
|
||||||
Doc.Header.SHOffset
|
Doc.Header.SHOffset
|
||||||
? (uint16_t)*Doc.Header.SHOffset
|
? (typename ELFT::uint)(*Doc.Header.SHOffset)
|
||||||
: sizeof(Header) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size();
|
: sizeof(Header) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size();
|
||||||
Header.e_shnum =
|
Header.e_shnum =
|
||||||
Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : SN2I.size() + 1;
|
Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : SN2I.size() + 1;
|
||||||
|
|
Loading…
Reference in New Issue