[llvm] 327c445 - [llvm-readobj] - Verify the location of program headers better.

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Wed Jul 15 02:37:45 PDT 2020


Author: Georgii Rymar
Date: 2020-07-15T12:37:23+03:00
New Revision: 327c4450353309ea97cbd9f56b46f099f3b0a1f9

URL: https://github.com/llvm/llvm-project/commit/327c4450353309ea97cbd9f56b46f099f3b0a1f9
DIFF: https://github.com/llvm/llvm-project/commit/327c4450353309ea97cbd9f56b46f099f3b0a1f9.diff

LOG: [llvm-readobj] - Verify the location of program headers better.

This improves condition in the ELFFile::program_headers().
Previously if was possible to read the headers from the wrong place when
the value of e_phoff was so large that computation overflowed.

Differential revision: https://reviews.llvm.org/D83774

Added: 
    

Modified: 
    llvm/include/llvm/Object/ELF.h
    llvm/test/tools/llvm-readobj/ELF/gnu-phdrs.test

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Object/ELF.h b/llvm/include/llvm/Object/ELF.h
index c7f2a8e709f0..b44dd3f48661 100644
--- a/llvm/include/llvm/Object/ELF.h
+++ b/llvm/include/llvm/Object/ELF.h
@@ -205,16 +205,18 @@ class ELFFile {
     if (getHeader()->e_phnum && getHeader()->e_phentsize != sizeof(Elf_Phdr))
       return createError("invalid e_phentsize: " +
                          Twine(getHeader()->e_phentsize));
-    if (getHeader()->e_phoff +
-            (getHeader()->e_phnum * getHeader()->e_phentsize) >
-        getBufSize())
+
+    uint64_t HeadersSize =
+        (uint64_t)getHeader()->e_phnum * getHeader()->e_phentsize;
+    uint64_t PhOff = getHeader()->e_phoff;
+    if (PhOff + HeadersSize < PhOff || PhOff + HeadersSize > getBufSize())
       return createError("program headers are longer than binary of size " +
                          Twine(getBufSize()) + ": e_phoff = 0x" +
                          Twine::utohexstr(getHeader()->e_phoff) +
                          ", e_phnum = " + Twine(getHeader()->e_phnum) +
                          ", e_phentsize = " + Twine(getHeader()->e_phentsize));
-    auto *Begin =
-        reinterpret_cast<const Elf_Phdr *>(base() + getHeader()->e_phoff);
+
+    auto *Begin = reinterpret_cast<const Elf_Phdr *>(base() + PhOff);
     return makeArrayRef(Begin, Begin + getHeader()->e_phnum);
   }
 

diff  --git a/llvm/test/tools/llvm-readobj/ELF/gnu-phdrs.test b/llvm/test/tools/llvm-readobj/ELF/gnu-phdrs.test
index d1d071f10ac6..1b5bb2572b11 100644
--- a/llvm/test/tools/llvm-readobj/ELF/gnu-phdrs.test
+++ b/llvm/test/tools/llvm-readobj/ELF/gnu-phdrs.test
@@ -356,7 +356,8 @@ ProgramHeaders:
     Offset: 0xAABBCCDDEEFF1122
 
 ## Check we report a warning when we are unable to read program headers.
-# RUN: yaml2obj --docnum=3 %s -o %t.phdr.err
+## Case A: the e_phentsize field is invalid.
+# RUN: yaml2obj --docnum=3 -DPHENTSIZE=1 %s -o %t.phdr.err
 # RUN: llvm-readelf --program-headers %t.phdr.err 2>&1 | \
 # RUN:   FileCheck %s -DFILE=%t.phdr.err --check-prefix=WARN-PHENTSIZE
 
@@ -373,7 +374,8 @@ FileHeader:
   Data:       ELFDATA2LSB
   Type:       ET_EXEC
   Machine:    EM_X86_64
-  EPhEntSize: 1
+  EPhEntSize: [[PHENTSIZE=56]]
+  EPhOff:     [[PHOFF=64]]
 Sections:
   - Name: .foo
     Type: SHT_PROGBITS
@@ -381,3 +383,28 @@ ProgramHeaders:
   - Type: PT_PHDR
     Sections:
       - Section: .foo
+
+## Case B: the value of the e_phoff field is invalid.
+
+## Check that we do not report a warning when the program header table ends right before the end of the file.
+## 0x160 + size of headers (56) == file size.
+# RUN: yaml2obj --docnum=3 -DPHOFF=0x160 %s -o %t.phdr.no.err2
+# RUN: llvm-readelf %t.phdr.no.err2 --program-headers 2>&1 | FileCheck %s --implicit-check-not=warning:
+
+## Check we report a warning when e_phoff goes 1 byte past the end of the file.
+# RUN: yaml2obj --docnum=3 -DPHOFF=0x161 %s -o %t.phdr.err2
+# RUN: llvm-readelf --program-headers %t.phdr.err2 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t.phdr.err2 --check-prefix=WARN-PHOFF -DOFF=0x161
+
+# WARN-PHOFF:      Program Headers:
+# WARN-PHOFF-NEXT:   Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
+# WARN-PHOFF-NEXT: warning: '[[FILE]]': unable to dump program headers: program headers are longer than binary of size 408: e_phoff = [[OFF]], e_phnum = 1, e_phentsize = 56
+# WARN-PHOFF:      Section to Segment mapping:
+# WARN-PHOFF-NEXT:   Segment Sections...
+# WARN-PHOFF-NEXT: warning: '[[FILE]]': can't read program headers to build section to segment mapping: program headers are longer than binary of size 408: e_phoff = [[OFF]], e_phnum = 1, e_phentsize = 56
+
+## Check we report a warning when the value of e_phoff is so large that
+## e_phoff + e_phnum * e_phentsize > UINT64_MAX.
+# RUN: yaml2obj --docnum=3 -DPHOFF=0xffffffffffffffff %s -o %t.phdr.err3
+# RUN: llvm-readelf --program-headers %t.phdr.err3 2>&1 | \
+# RUN:   FileCheck %s -DFILE=%t.phdr.err3 --check-prefix=WARN-PHOFF -DOFF=0xffffffffffffffff


        


More information about the llvm-commits mailing list