[llvm] aa456a6 - [llvm-readobj/elf] - Refine the code for broken PT_DYNAMIC segment diagnostic.

Georgii Rymar via llvm-commits llvm-commits at lists.llvm.org
Fri Aug 21 05:06:27 PDT 2020


Author: Georgii Rymar
Date: 2020-08-21T15:05:46+03:00
New Revision: aa456a6df4931541c6aaf0e60a77cc646b5ad4c4

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

LOG: [llvm-readobj/elf] - Refine the code for broken PT_DYNAMIC segment diagnostic.

The code that reports "PT_DYNAMIC segment offset + size exceeds the size of the file"
has an issue: it is possible to bypass the validation by overflowing the size + offset result.

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

Added: 
    

Modified: 
    llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
    llvm/tools/llvm-readobj/ELFDumper.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test b/llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
index 2f878e79607a..b7a44a7bc0f7 100644
--- a/llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
+++ b/llvm/test/tools/llvm-readobj/ELF/malformed-pt-dynamic.test
@@ -51,9 +51,72 @@
 
 # WARN2-NOHEADERS: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1119) + file size (0x10) exceeds the size of the file (0x1118)
 
+## Case C: test we report a warning when the offset + the file size of the PT_DYNAMIC is so large a
+##         value that it overflows the platform address size type.
+
+# RUN: yaml2obj %s -DOFFSET=0xffffffffffffffff -o %t3
+# RUN: not llvm-readobj %t3 --dynamic-table 2>&1 | FileCheck -DFILE=%t3 %s --check-prefix=WARN3
+# RUN: not llvm-readelf %t3 --dynamic-table 2>&1 | FileCheck -DFILE=%t3 %s --check-prefix=WARN3
+
+# WARN3: warning: '[[FILE]]': PT_DYNAMIC segment offset (0xffffffffffffffff) + file size (0x10) exceeds the size of the file (0x1130)
+# WARN3: error:   '[[FILE]]': Invalid data was encountered while parsing the file
+
+# RUN: yaml2obj %s -DNOHEADERS=true -DOFFSET=0xffffffffffffffff -o %t3.noheaders
+# RUN: llvm-readobj %t3.noheaders --dynamic-table 2>&1 | \
+# RUN:   FileCheck -DFILE=%t3.noheaders %s --check-prefix=WARN3-NOHEADERS
+# RUN: llvm-readelf %t3.noheaders --dynamic-table 2>&1 | \
+# RUN:   FileCheck -DFILE=%t3.noheaders %s --check-prefix=WARN3-NOHEADERS
+
+# WARN3-NOHEADERS: warning: '[[FILE]]': PT_DYNAMIC segment offset (0xffffffffffffffff) + file size (0x10) exceeds the size of the file (0x1118)
+
+# RUN: yaml2obj %s -DFILESIZE=0xffffffffffffffff -o %t4
+# RUN: llvm-readobj %t4 --dynamic-table 2>&1 | FileCheck -DFILE=%t4 %s --check-prefix=WARN4
+# RUN: llvm-readelf %t4 --dynamic-table 2>&1 | FileCheck -DFILE=%t4 %s --check-prefix=WARN4
+
+# WARN4: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1000) + file size (0xffffffffffffffff) exceeds the size of the file (0x1130)
+
+# RUN: yaml2obj %s -DNOHEADERS=true -DFILESIZE=0xffffffffffffffff -o %t4.noheaders
+# RUN: llvm-readobj %t4.noheaders --dynamic-table 2>&1 | \
+# RUN:   FileCheck -DFILE=%t4.noheaders %s --check-prefix=WARN4-NOHEADERS
+# RUN: llvm-readelf %t4.noheaders --dynamic-table 2>&1 | \
+# RUN:   FileCheck -DFILE=%t4.noheaders %s --check-prefix=WARN4-NOHEADERS
+
+# WARN4-NOHEADERS: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1000) + file size (0xffffffffffffffff) exceeds the size of the file (0x1118)
+
+## Case D: the same as "Case C", but for a 32-bit object.
+
+# RUN: yaml2obj %s -DBITS=32 -DOFFSET=0xffffffff -o %t5
+# RUN: not llvm-readobj %t5 --dynamic-table 2>&1 | FileCheck -DFILE=%t5 %s --check-prefix=WARN5
+# RUN: not llvm-readelf %t5 --dynamic-table 2>&1 | FileCheck -DFILE=%t5 %s --check-prefix=WARN5
+
+# WARN5: warning: '[[FILE]]': PT_DYNAMIC segment offset (0xffffffff) + file size (0x8) exceeds the size of the file (0x10c8)
+# WARN5: error:   '[[FILE]]': Invalid data was encountered while parsing the file
+
+# RUN: yaml2obj %s -DNOHEADERS=true -DBITS=32 -DOFFSET=0xffffffff -o %t5.noheaders
+# RUN: llvm-readobj %t5.noheaders --dynamic-table 2>&1 | \
+# RUN:   FileCheck -DFILE=%t5.noheaders %s --check-prefix=WARN5-NOHEADERS
+# RUN: llvm-readelf %t5.noheaders --dynamic-table 2>&1 | \
+# RUN:   FileCheck -DFILE=%t5.noheaders %s --check-prefix=WARN5-NOHEADERS
+
+# WARN5-NOHEADERS: warning: '[[FILE]]': PT_DYNAMIC segment offset (0xffffffff) + file size (0x8) exceeds the size of the file (0x10ac)
+
+# RUN: yaml2obj %s -DBITS=32 -DFILESIZE=0xffffffff -o %t6
+# RUN: llvm-readobj %t6 --dynamic-table 2>&1 | FileCheck -DFILE=%t6 %s --check-prefix=WARN6
+# RUN: llvm-readelf %t6 --dynamic-table 2>&1 | FileCheck -DFILE=%t6 %s --check-prefix=WARN6
+
+# WARN6: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1000) + file size (0xffffffff) exceeds the size of the file (0x10c8)
+
+# RUN: yaml2obj %s -DNOHEADERS=true -DBITS=32 -DFILESIZE=0xffffffff -o %t6.noheaders
+# RUN: llvm-readobj %t6.noheaders --dynamic-table 2>&1 | \
+# RUN:   FileCheck -DFILE=%t6.noheaders %s --check-prefix=WARN6-NOHEADERS
+# RUN: llvm-readelf %t6.noheaders --dynamic-table 2>&1 | \
+# RUN:   FileCheck -DFILE=%t6.noheaders %s --check-prefix=WARN6-NOHEADERS
+
+# WARN6-NOHEADERS: warning: '[[FILE]]': PT_DYNAMIC segment offset (0x1000) + file size (0xffffffff) exceeds the size of the file (0x10ac)
+
 --- !ELF
 FileHeader:
-  Class: ELFCLASS64
+  Class: ELFCLASS[[BITS=64]]
   Data:  ELFDATA2LSB
   Type:  ET_EXEC
 Sections:

diff  --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index c321f4585e47..23c58678a4a2 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -245,12 +245,10 @@ template <typename ELFT> class ELFDumper : public ObjDumper {
 
   DynRegionInfo createDRI(uint64_t Offset, uint64_t Size, uint64_t EntSize) {
     const ELFFile<ELFT> *Obj = ObjF->getELFFile();
-    const uint8_t *Addr = Obj->base() + Offset;
-    if (Addr < Obj->base() || Addr + Size > Obj->base() + Obj->getBufSize())
+    if (Offset + Size < Offset || Offset + Size > Obj->getBufSize())
       reportError(errorCodeToError(llvm::object::object_error::parse_failed),
                   ObjF->getFileName());
-
-    return {Addr, Size, EntSize, ObjF->getFileName()};
+    return {Obj->base() + Offset, Size, EntSize, ObjF->getFileName()};
   }
 
   void printAttributes();
@@ -1881,8 +1879,10 @@ ELFDumper<ELFT>::findDynamic(const ELFFile<ELFT> *Obj) {
     break;
   }
 
-  if (DynamicPhdr && DynamicPhdr->p_offset + DynamicPhdr->p_filesz >
-                         ObjF->getMemoryBufferRef().getBufferSize()) {
+  if (DynamicPhdr && ((DynamicPhdr->p_offset + DynamicPhdr->p_filesz >
+                       ObjF->getMemoryBufferRef().getBufferSize()) ||
+                      (DynamicPhdr->p_offset + DynamicPhdr->p_filesz <
+                       DynamicPhdr->p_offset))) {
     reportUniqueWarning(createError(
         "PT_DYNAMIC segment offset (0x" +
         Twine::utohexstr(DynamicPhdr->p_offset) + ") + file size (0x" +


        


More information about the llvm-commits mailing list