[llvm] r266248 - Start to add real error messages for malformed Mach-O files.

Kevin Enderby via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 13 14:17:58 PDT 2016


Author: enderby
Date: Wed Apr 13 16:17:58 2016
New Revision: 266248

URL: http://llvm.org/viewvc/llvm-project?rev=266248&view=rev
Log:
Start to add real error messages for malformed Mach-O files.
And update the existing test cases in test/Object/macho-invalid.test
to use llvm-objdump with the -macho option to produce these
error messages and stop producing the generic "Invalid data
was encountered while parsing the file" message.

Working from the beginning of the file, if the mach header is too large for
the size of the file and then if the load commands that follow extend past
the end of the file these two errors now generate correct error messages.

Both of these have existing test cases in test/Object/macho-invalid.test .

But the first with macho-invalid-header it will never trigger the error message
"mach header extends past the end of the file" using any of the llvm tools as
they all use identify_magic() which rejects files with the correct magic number
that are too small in size.  So I tested this by hacking that code and seeing the
error message down in parseHeader() really does happen.  So in case there
is ever code in llvm that directly calls createMachOObjectFile() this error
message will be correctly produced.

The second error message of "load commands extends past the end of the file"
is triggered by a number of existing tests cases in test/Object/macho-invalid.test .
Also other tests trigger different error messages now like "ilocalsym plus
nlocalsym in LC_DYSYMTAB load command extends past the end of the
symbol table".

There are two existing test cases that still get the "Invalid data was encountered ..."
error messages that I will tackle next.  But they will involve a bit of pluming an
Expect<...> up through the call stack and I want to do those as separate changes.

FYI, for those test cases that were trying to test specific errors that now get
different errors I’ll fix those in follow on changes and create new test cases
for those so they test the error they were meant to test.

Modified:
    llvm/trunk/lib/Object/MachOObjectFile.cpp
    llvm/trunk/test/Object/macho-invalid.test

Modified: llvm/trunk/lib/Object/MachOObjectFile.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Object/MachOObjectFile.cpp?rev=266248&r1=266247&r2=266248&view=diff
==============================================================================
--- llvm/trunk/lib/Object/MachOObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/MachOObjectFile.cpp Wed Apr 13 16:17:58 2016
@@ -208,6 +208,11 @@ getNextLoadCommandInfo(const MachOObject
 template <typename T>
 static void parseHeader(const MachOObjectFile *Obj, T &Header,
                         Error &Err) {
+  if (sizeof(T) > Obj->getData().size()) {
+    Err = malformedError(*Obj, "truncated or malformed object (the mach header "
+                         "extends past the end of the file)");
+    return;
+  }
   if (auto HeaderOrErr = getStructOrErr<T>(Obj, getPtr(Obj, 0)))
     Header = *HeaderOrErr;
   else
@@ -267,12 +272,22 @@ MachOObjectFile::MachOObjectFile(MemoryB
       DyldInfoLoadCmd(nullptr), UuidLoadCmd(nullptr),
       HasPageZeroSegment(false) {
   ErrorAsOutParameter ErrAsOutParam(Err);
-  if (is64Bit())
+  uint64_t big_size;
+  if (is64Bit()) {
     parseHeader(this, Header64, Err);
-  else
+    big_size = sizeof(MachO::mach_header_64);
+  } else {
     parseHeader(this, Header, Err);
+    big_size = sizeof(MachO::mach_header);
+  }
   if (Err)
     return;
+  big_size += getHeader().sizeofcmds;
+  if (getData().data() + big_size > getData().end()) {
+    Err = malformedError(getFileName(), "truncated or malformed object "
+                         "(load commands extends past the end of the file)");
+    return;
+  }
 
   uint32_t LoadCommandCount = getHeader().ncmds;
   if (LoadCommandCount == 0)

Modified: llvm/trunk/test/Object/macho-invalid.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/macho-invalid.test?rev=266248&r1=266247&r2=266248&view=diff
==============================================================================
--- llvm/trunk/test/Object/macho-invalid.test (original)
+++ llvm/trunk/test/Object/macho-invalid.test Wed Apr 13 16:17:58 2016
@@ -9,11 +9,11 @@ RUN: not llvm-objdump -macho -private-he
 RUN:      | FileCheck -check-prefix INCOMPLETE-LOADC %s
 INCOMPLETE-LOADC: truncated or malformed object (load command 0 extends past the end all load commands in the file)
 
-RUN: not llvm-objdump -private-headers %p/Inputs/macho-invalid-too-small-load-command 2>&1 \
+RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-too-small-load-command 2>&1 \
 RUN:      | FileCheck -check-prefix SMALL-LOADC-SIZE %s
-RUN: not llvm-objdump -private-headers %p/Inputs/macho64-invalid-too-small-load-command 2>&1 \
+RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho64-invalid-too-small-load-command 2>&1 \
 RUN:      | FileCheck -check-prefix SMALL-LOADC-SIZE %s
-SMALL-LOADC-SIZE: Mach-O load command with size < 8 bytes
+SMALL-LOADC-SIZE: truncated or malformed object (load commands extends past the end of the file)
 
 RUN: not llvm-objdump -private-headers %p/Inputs/macho-invalid-too-small-segment-load-command 2>&1 \
 RUN:      | FileCheck -check-prefix SMALL-SEGLOADC-SIZE %s
@@ -27,13 +27,12 @@ RUN: not llvm-objdump -private-headers %
 RUN:      | FileCheck -check-prefix TOO-MANY-SECTS %s
 TOO-MANY-SECTS: Mach-O segment load command contains too many sections
 
-RUN: not llvm-objdump -t %p/Inputs/macho-invalid-bad-symbol-index 2>&1 \
+RUN: not llvm-objdump -macho -t %p/Inputs/macho-invalid-bad-symbol-index 2>&1 \
 RUN:      | FileCheck -check-prefix BAD-SYMBOL %s
-BAD-SYMBOL: Invalid data was encountered while parsing the file.
-RUN: llvm-objdump -t %p/Inputs/macho-valid-0-nsyms 2>&1 \
+BAD-SYMBOL: truncated or malformed object (ilocalsym plus nlocalsym in LC_DYSYMTAB load command extends past the end of the symbol table)
+RUN: llvm-objdump -macho -t %p/Inputs/macho-valid-0-nsyms 2>&1 \
 RUN:      | FileCheck -check-prefix ZERO-NSYMS %s
 ZERO-NSYMS: SYMBOL TABLE
-ZERO-NSYMS-NOT: Requested symbol index is out of range
 
 RUN: not llvm-objdump -t %p/Inputs/macho-invalid-symbol-name-past-eof 2>&1 \
 RUN:      | FileCheck -check-prefix NAME-PAST-EOF %s
@@ -58,9 +57,8 @@ RUN: not llvm-objdump -t %p/Inputs/macho
 RUN:      | FileCheck -check-prefix INVALID-SECTION-IDX-SYMBOL-SEC-objdump %s
 INVALID-SECTION-IDX-SYMBOL-SEC-objdump: Invalid data was encountered while parsing the file.
 
-RUN: not llvm-objdump -private-headers %p/Inputs/macho-invalid-header 2>&1 | FileCheck -check-prefix INVALID-HEADER %s
-INVALID-HEADER: The file was not recognized as a valid object file.
-NOT-INVALID-HEADER: Invalid data was encountered while parsing the file.
+RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-header 2>&1 | FileCheck -check-prefix INVALID-HEADER %s
+INVALID-HEADER: The file was not recognized as a valid object file
 
-RUN: not llvm-objdump -private-headers %p/Inputs/macho64-invalid-incomplete-segment-load-command 2>&1 | FileCheck -check-prefix INCOMPLETE-SEGMENT-LOADC %s
-INCOMPLETE-SEGMENT-LOADC: Invalid data was encountered while parsing the file
+RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho64-invalid-incomplete-segment-load-command 2>&1 | FileCheck -check-prefix INCOMPLETE-SEGMENT-LOADC %s
+INCOMPLETE-SEGMENT-LOADC: truncated or malformed object (load commands extends past the end of the file)




More information about the llvm-commits mailing list