Skip to content

Commit ec10d5c

Browse files
author
George Rimar
committed
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
1 parent b9d96ce commit ec10d5c

File tree

4 files changed

+68
-6
lines changed

4 files changed

+68
-6
lines changed

llvm/include/llvm/Object/ELF.h

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -495,7 +495,8 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
495495
Twine(getHeader()->e_shentsize));
496496

497497
const uint64_t FileSize = Buf.size();
498-
if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize)
498+
if (SectionTableOffset + sizeof(Elf_Shdr) > FileSize ||
499+
SectionTableOffset + (uintX_t)sizeof(Elf_Shdr) < SectionTableOffset)
499500
return createError(
500501
"section header table goes past the end of the file: e_shoff = 0x" +
501502
Twine::utohexstr(SectionTableOffset));
@@ -513,15 +514,22 @@ Expected<typename ELFT::ShdrRange> ELFFile<ELFT>::sections() const {
513514
NumSections = First->sh_size;
514515

515516
if (NumSections > UINT64_MAX / sizeof(Elf_Shdr))
516-
// TODO: this error is untested.
517-
return createError("section table goes past the end of file");
517+
return createError("invalid number of sections specified in the NULL "
518+
"section's sh_size field (" +
519+
Twine(NumSections) + ")");
518520

519521
const uint64_t SectionTableSize = NumSections * sizeof(Elf_Shdr);
522+
if (SectionTableOffset + SectionTableSize < SectionTableOffset)
523+
return createError(
524+
"invalid section header table offset (e_shoff = 0x" +
525+
Twine::utohexstr(SectionTableOffset) +
526+
") or invalid number of sections specified in the first section "
527+
"header's sh_size field (0x" +
528+
Twine::utohexstr(NumSections) + ")");
520529

521530
// Section table goes past end of file!
522531
if (SectionTableOffset + SectionTableSize > FileSize)
523532
return createError("section table goes past the end of file");
524-
525533
return makeArrayRef(First, NumSections);
526534
}
527535

llvm/include/llvm/ObjectYAML/ELFYAML.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ struct FileHeader {
7777
llvm::yaml::Hex64 Entry;
7878

7979
Optional<llvm::yaml::Hex16> SHEntSize;
80-
Optional<llvm::yaml::Hex16> SHOffset;
80+
Optional<llvm::yaml::Hex64> SHOffset;
8181
Optional<llvm::yaml::Hex16> SHNum;
8282
Optional<llvm::yaml::Hex16> SHStrNdx;
8383
};

llvm/test/Object/invalid.test

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,3 +552,57 @@ FileHeader:
552552
Sections:
553553
- Name: .foo
554554
Type: SHT_PROGBITS
555+
556+
## We report an error if the number of sections stored in sh_size
557+
## is greater than UINT64_MAX / sizeof(Elf_Shdr) == 288230376151711743.
558+
## Here we check that do not crash on a border value.
559+
560+
# RUN: yaml2obj --docnum=26 %s -o %t26
561+
# RUN: not llvm-readobj -h %t26 2>&1 | FileCheck -DFILE=%t26 --check-prefix=INVALID-SEC-NUM1 %s
562+
563+
# 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)
564+
565+
--- !ELF
566+
FileHeader:
567+
Class: ELFCLASS64
568+
Data: ELFDATA2LSB
569+
Type: ET_REL
570+
Machine: EM_X86_64
571+
SHNum: 0x0
572+
Sections:
573+
- Type: SHT_NULL
574+
Size: 288230376151711743
575+
576+
## See above, but now we test the UINT64_MAX / sizeof(Elf_Shdr) value.
577+
## The error is slightly different in this case.
578+
579+
# RUN: yaml2obj --docnum=27 %s -o %t27
580+
# RUN: not llvm-readobj -h %t27 2>&1 | FileCheck -DFILE=%t27 --check-prefix=INVALID-SEC-NUM2 %s
581+
582+
# INVALID-SEC-NUM2: error: '[[FILE]]': invalid number of sections specified in the NULL section's sh_size field (288230376151711744)
583+
584+
--- !ELF
585+
FileHeader:
586+
Class: ELFCLASS64
587+
Data: ELFDATA2LSB
588+
Type: ET_REL
589+
Machine: EM_X86_64
590+
SHNum: 0x0
591+
Sections:
592+
- Type: SHT_NULL
593+
Size: 288230376151711744
594+
595+
## Check the case when SHOffset is too large. SHOffset + sizeof(Elf_Shdr) overflows the uint64 type.
596+
597+
# RUN: yaml2obj --docnum=28 %s -o %t28
598+
# RUN: not llvm-readobj -h %t28 2>&1 | FileCheck -DFILE=%t28 --check-prefix=INVALID-SEC-NUM3 %s
599+
600+
# INVALID-SEC-NUM3: error: '[[FILE]]': section header table goes past the end of the file: e_shoff = 0xffffffffffffffff
601+
602+
--- !ELF
603+
FileHeader:
604+
Class: ELFCLASS64
605+
Data: ELFDATA2LSB
606+
Type: ET_REL
607+
Machine: EM_X86_64
608+
SHOffset: 0xffffffffffffffff

llvm/tools/yaml2obj/yaml2elf.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) {
244244
// Immediately following the ELF header and program headers.
245245
Header.e_shoff =
246246
Doc.Header.SHOffset
247-
? (uint16_t)*Doc.Header.SHOffset
247+
? (typename ELFT::uint)(*Doc.Header.SHOffset)
248248
: sizeof(Header) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size();
249249
Header.e_shnum =
250250
Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : SN2I.size() + 1;

0 commit comments

Comments
 (0)