Fix a bug in llvm-objdump’s printing of Objective-C meta data
authorKevin Enderby <enderby@apple.com>
Thu, 8 Oct 2015 22:50:55 +0000 (22:50 +0000)
committerKevin Enderby <enderby@apple.com>
Thu, 8 Oct 2015 22:50:55 +0000 (22:50 +0000)
from malformed Mach-O files that caused a crash because of a
section header had a size that extended past the end of the file.

rdar://22983603

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@249768 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Object/MachOObjectFile.cpp
test/tools/llvm-objdump/Inputs/malformed-machos/mem-crup-0040.macho [new file with mode: 0644]
test/tools/llvm-objdump/malformed-machos.test
tools/llvm-objdump/MachODump.cpp

index f89e8e485945dbc4fccbe1caabff6a3406c17fc0..4f9ccedd0c6936e0a19eab4ea1be41f26b052d6c 100644 (file)
@@ -483,9 +483,32 @@ uint64_t MachOObjectFile::getSectionAddress(DataRefImpl Sec) const {
 }
 
 uint64_t MachOObjectFile::getSectionSize(DataRefImpl Sec) const {
-  if (is64Bit())
-    return getSection64(Sec).size;
-  return getSection(Sec).size;
+  // In the case if a malformed Mach-O file where the section offset is past
+  // the end of the file or some part of the section size is past the end of
+  // the file return a size of zero or a size that covers the rest of the file
+  // but does not extend past the end of the file.
+  uint32_t SectOffset, SectType;
+  uint64_t SectSize;
+
+  if (is64Bit()) {
+    MachO::section_64 Sect = getSection64(Sec);
+    SectOffset = Sect.offset;
+    SectSize = Sect.size;
+    SectType = Sect.flags & MachO::SECTION_TYPE;
+  } else {
+    MachO::section Sect = getSection(Sec);
+    SectOffset = Sect.offset;
+    SectSize = Sect.size;
+    SectType = Sect.flags & MachO::SECTION_TYPE;
+  }
+  if (SectType == MachO::S_ZEROFILL || SectType == MachO::S_GB_ZEROFILL)
+    return SectSize;
+  uint64_t FileSize = getData().size();
+  if (SectOffset > FileSize)
+    return 0;
+  if (FileSize - SectOffset < SectSize)
+    return FileSize - SectOffset;
+  return SectSize;
 }
 
 std::error_code MachOObjectFile::getSectionContents(DataRefImpl Sec,
diff --git a/test/tools/llvm-objdump/Inputs/malformed-machos/mem-crup-0040.macho b/test/tools/llvm-objdump/Inputs/malformed-machos/mem-crup-0040.macho
new file mode 100644 (file)
index 0000000..f0765a4
Binary files /dev/null and b/test/tools/llvm-objdump/Inputs/malformed-machos/mem-crup-0040.macho differ
index e836239a250694c871f1b689ac8a8b4a40284ae0..2167c7065509679645cf707d6d93f44356a9f61b 100644 (file)
@@ -18,3 +18,9 @@
 # RUN:   | FileCheck -check-prefix=m0010 %s 
 
 # m0010: 00000000000010e0 0x10e8 _OBJC_CLASS_
+
+# RUN: llvm-objdump -macho -objc-meta-data \
+# RUN:   %p/Inputs/malformed-machos/mem-crup-0040.macho \
+# RUN:   | FileCheck -check-prefix=m0040 %s 
+
+# m0040: 00000000000010a0 0xf39 -[tiny_dylib init]
index b6b910f55dc749422a3497fde77867154ebb2639..993e9e6817b375a46a56bdcb6619860f55e028a9 100644 (file)
@@ -2340,6 +2340,8 @@ static const char *get_pointer_64(uint64_t Address, uint32_t &offset,
   for (unsigned SectIdx = 0; SectIdx != info->Sections->size(); SectIdx++) {
     uint64_t SectAddress = ((*(info->Sections))[SectIdx]).getAddress();
     uint64_t SectSize = ((*(info->Sections))[SectIdx]).getSize();
+    if (SectSize == 0)
+      continue;
     if (objc_only) {
       StringRef SectName;
       ((*(info->Sections))[SectIdx]).getName(SectName);