]> granicus.if.org Git - llvm/commitdiff
Change all but the last ErrorOr<...> use for MachOUniversalBinary to Expected<.....
authorKevin Enderby <enderby@apple.com>
Mon, 27 Jun 2016 21:39:39 +0000 (21:39 +0000)
committerKevin Enderby <enderby@apple.com>
Mon, 27 Jun 2016 21:39:39 +0000 (21:39 +0000)
allow a good error message to be produced.

I added the one test case that the object file tools could produce an error
message.  The other two errors can’t be triggered if the input file is passed
through sys::fs::identify_magic().  But the malformedError("bad magic number")
does get triggered by the logic in llvm-dsymutil when dealing with a normal
Mach-O file.  The other "File too small ..." error would take a logic error
currently to produce and is not tested for.

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

include/llvm/Object/MachOUniversal.h
lib/Object/Binary.cpp
lib/Object/MachOUniversal.cpp
test/Object/Inputs/macho-invalid-fat [new file with mode: 0644]
test/Object/macho-invalid.test
tools/dsymutil/BinaryHolder.cpp

index d384b5ff60bffb69f9140033b75080cb590baefc..f4c2eacf181cc725ee9118316a7538e8dca4d26f 100644 (file)
@@ -128,8 +128,8 @@ public:
     }
   };
 
-  MachOUniversalBinary(MemoryBufferRef Souce, std::error_code &EC);
-  static ErrorOr<std::unique_ptr<MachOUniversalBinary>>
+  MachOUniversalBinary(MemoryBufferRef Souce, Error &Err);
+  static Expected<std::unique_ptr<MachOUniversalBinary>>
   create(MemoryBufferRef Source);
 
   object_iterator begin_objects() const {
index 723b279d9e691be3751a0024f91177f921d7495d..8d03a2a976be271da9c5516d83accf29d37cae72 100644 (file)
@@ -65,7 +65,7 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
     case sys::fs::file_magic::bitcode:
       return ObjectFile::createSymbolicFile(Buffer, Type, Context);
     case sys::fs::file_magic::macho_universal_binary:
-      return errorOrToExpected(MachOUniversalBinary::create(Buffer));
+      return MachOUniversalBinary::create(Buffer);
     case sys::fs::file_magic::unknown:
     case sys::fs::file_magic::windows_resource:
       // Unrecognized object file format.
index b3b0c251c1005934227eb2147f39946ff852cd62..e6880587cde5ef06b6009d72395cec832b0bcb30 100644 (file)
 using namespace llvm;
 using namespace object;
 
+static Error
+malformedError(Twine Msg) {
+  std::string StringMsg = "truncated or malformed fat file (" + Msg.str() + ")";
+  return make_error<GenericBinaryError>(std::move(StringMsg),
+                                        object_error::parse_failed);
+}
+
 template<typename T>
 static T getUniversalBinaryStruct(const char *Ptr) {
   T Res;
@@ -92,22 +99,24 @@ MachOUniversalBinary::ObjectForArch::getAsArchive() const {
 
 void MachOUniversalBinary::anchor() { }
 
-ErrorOr<std::unique_ptr<MachOUniversalBinary>>
+Expected<std::unique_ptr<MachOUniversalBinary>>
 MachOUniversalBinary::create(MemoryBufferRef Source) {
-  std::error_code EC;
+  Error Err;
   std::unique_ptr<MachOUniversalBinary> Ret(
-      new MachOUniversalBinary(Source, EC));
-  if (EC)
-    return EC;
+      new MachOUniversalBinary(Source, Err));
+  if (Err)
+    return std::move(Err);
   return std::move(Ret);
 }
 
-MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source,
-                                           std::error_code &ec)
+MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source, Error &Err)
     : Binary(Binary::ID_MachOUniversalBinary, Source), Magic(0),
       NumberOfObjects(0) {
+  ErrorAsOutParameter ErrAsOutParam(Err);
   if (Data.getBufferSize() < sizeof(MachO::fat_header)) {
-    ec = object_error::invalid_file_type;
+    Err = make_error<GenericBinaryError>("File too small to be a Mach-O "
+                                         "universal file",
+                                         object_error::invalid_file_type);
     return;
   }
   // Check for magic value and sufficient header size.
@@ -121,14 +130,16 @@ MachOUniversalBinary::MachOUniversalBinary(MemoryBufferRef Source,
   else if (Magic == MachO::FAT_MAGIC_64)
     MinSize += sizeof(MachO::fat_arch_64) * NumberOfObjects;
   else {
-    ec = object_error::parse_failed;
+    Err = malformedError("bad magic number");
     return;
   }
   if (Buf.size() < MinSize) {
-    ec = object_error::parse_failed;
+    Err = malformedError("fat_arch" +
+                         Twine(Magic == MachO::FAT_MAGIC ? "" : "_64") +
+                         " structs would extend past the end of the file");
     return;
   }
-  ec = std::error_code();
+  Err = Error::success();
 }
 
 Expected<std::unique_ptr<MachOObjectFile>>
diff --git a/test/Object/Inputs/macho-invalid-fat b/test/Object/Inputs/macho-invalid-fat
new file mode 100644 (file)
index 0000000..1fa0190
Binary files /dev/null and b/test/Object/Inputs/macho-invalid-fat differ
index 3fe6296645b51392d8e8a3be647823bf57108729..4c66f5c402e6d7a5b9b2c484c42143ac9fa8fce9 100644 (file)
@@ -94,3 +94,6 @@ INCOMPLETE-SEGMENT-LOADC-FAT: macho-universal-bad2.x86_64.i386 (for architecture
 
 RUN: not llvm-objdump -macho -private-headers -arch all %p/Inputs/macho-universal-archive-bad2.x86_64.i386 2>&1 | FileCheck -check-prefix INCOMPLETE-SEGMENT-LOADC-FAT-ARCHIVE %s
 INCOMPLETE-SEGMENT-LOADC-FAT-ARCHIVE: macho-universal-archive-bad2.x86_64.i386(macho64-invalid-incomplete-segment-load-command) (for architecture x86_64) truncated or malformed object (load commands extend past the end of the file)
+
+RUN: not llvm-objdump -macho -universal-headers %p/Inputs/macho-invalid-fat 2>&1 | FileCheck -check-prefix INVALID-FAT %s
+INVALID-FAT: truncated or malformed fat file (fat_arch_64 structs would extend past the end of the file)
index 32d176645bf94e2f33e02b09abd5fe5f4f87aff4..8f33657dd559427dfc1970937f2e028d8e26f077 100644 (file)
@@ -73,7 +73,8 @@ BinaryHolder::GetMemoryBuffersForFile(StringRef Filename,
 
   auto ErrOrFat = object::MachOUniversalBinary::create(
       CurrentMemoryBuffer->getMemBufferRef());
-  if (ErrOrFat.getError()) {
+  if (!ErrOrFat) {
+    consumeError(ErrOrFat.takeError());
     // Not a fat binary must be a standard one. Return a one element vector.
     return std::vector<MemoryBufferRef>{CurrentMemoryBuffer->getMemBufferRef()};
   }
@@ -145,7 +146,8 @@ BinaryHolder::MapArchiveAndGetMemberBuffers(StringRef Filename,
   std::vector<MemoryBufferRef> ArchiveBuffers;
   auto ErrOrFat = object::MachOUniversalBinary::create(
       CurrentMemoryBuffer->getMemBufferRef());
-  if (ErrOrFat.getError()) {
+  if (!ErrOrFat) {
+    consumeError(ErrOrFat.takeError());
     // Not a fat binary must be a standard one.
     ArchiveBuffers.push_back(CurrentMemoryBuffer->getMemBufferRef());
   } else {