[PATCH] [Object, MachO] Don't crash on parsing invalid MachO header.

Alexey Samsonov vonosmas at gmail.com
Wed Jun 3 16:44:27 PDT 2015


Hi rafael,

Instead, properly report this error from MachOObjectFile constructor.

http://reviews.llvm.org/D10227

Files:
  lib/Object/MachOObjectFile.cpp
  test/Object/Inputs/macho-invalid-header
  test/Object/macho-invalid.test

Index: lib/Object/MachOObjectFile.cpp
===================================================================
--- lib/Object/MachOObjectFile.cpp
+++ lib/Object/MachOObjectFile.cpp
@@ -38,6 +38,7 @@
   };
 }
 
+// FIXME: Replace all uses of this function with getStructOrErr.
 template <typename T>
 static T getStruct(const MachOObjectFile *O, const char *P) {
   // Don't read before the beginning or past the end of the file
@@ -51,6 +52,19 @@
   return Cmd;
 }
 
+template <typename T>
+static ErrorOr<T> getStructOrErr(const MachOObjectFile *O, const char *P) {
+  // Don't read before the beginning or past the end of the file
+  if (P < O->getData().begin() || P + sizeof(T) > O->getData().end())
+    return object_error::parse_failed;
+
+  T Cmd;
+  memcpy(&Cmd, P, sizeof(T));
+  if (O->isLittleEndian() != sys::IsLittleEndianHost)
+    MachO::swapStruct(Cmd);
+  return Cmd;
+}
+
 template <typename SegmentCmd>
 static uint32_t getSegmentLoadCommandNumSections(const SegmentCmd &S,
                                                  uint32_t Cmdsize) {
@@ -180,6 +194,16 @@
   return Sect.flags;
 }
 
+template <typename T>
+static void parseHeader(const MachOObjectFile *Obj, T &Header,
+                        std::error_code &EC) {
+  auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0));
+  if (HeaderOrErr)
+    Header = HeaderOrErr.get();
+  else
+    EC = HeaderOrErr.getError();
+}
+
 MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
                                  bool Is64bits, std::error_code &EC)
     : ObjectFile(getMachOType(IsLittleEndian, Is64bits), Object),
@@ -190,9 +214,11 @@
       HasPageZeroSegment(false) {
   // Parse header.
   if (is64Bit())
-    Header64 = getStruct<MachO::mach_header_64>(this, getPtr(this, 0));
+    parseHeader(this, Header64, EC);
   else
-    *Header = getStruct<MachO::mach_header>(this, getPtr(this, 0));
+    parseHeader(this, *Header, EC);
+  if (EC)
+    return;
 
   uint32_t LoadCommandCount = Header->ncmds;
   if (LoadCommandCount == 0)
Index: test/Object/macho-invalid.test
===================================================================
--- test/Object/macho-invalid.test
+++ test/Object/macho-invalid.test
@@ -28,11 +28,14 @@
 RUN: not llvm-nm %p/Inputs/macho-invalid-section-index-getSectionRawName 2>&1 \
 RUN:      | FileCheck -check-prefix INVALID-SECTION-IDX-SYMBOL-SEC %s
 
+RUN: llvm-objdump -private-headers %p/Inputs/macho-invalid-header 2>&1 | FileCheck -check-prefix INVALID-HEADER %s
+
 SMALL-LOADC-SIZE: Load command with size < 8 bytes
 SMALL-SEGLOADC-SIZE: Segment load command size is too small
 INCOMPLETE-LOADC: Malformed MachO file
 TOO-MANY-SECTS: Number of sections too large for size of load command
 BAD-SYMBOL: Requested symbol index is out of range
 NAME-PAST-EOF: Symbol name entry points before beginning or past end of file
 
 INVALID-SECTION-IDX-SYMBOL-SEC: getSymbolSection: Invalid section index
+INVALID-HEADER: Invalid data was encountered while parsing the file.

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D10227.27071.patch
Type: text/x-patch
Size: 3008 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150603/fa5ced94/attachment.bin>


More information about the llvm-commits mailing list