[llvm] r285632 - More additional error checks for invalid Mach-O files when
Kevin Enderby via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 31 13:29:48 PDT 2016
Author: enderby
Date: Mon Oct 31 15:29:48 2016
New Revision: 285632
URL: http://llvm.org/viewvc/llvm-project?rev=285632&view=rev
Log:
More additional error checks for invalid Mach-O files when
the offsets and sizes of an element of the file overlaps with
another element in the Mach-O file.
This shows the approach to this testing for three elements
and contains for tests for their overlap. Checking for all the
remain elements will be added next.
Added:
llvm/trunk/test/Object/Inputs/macho-invalid-strtab-overlap (with props)
llvm/trunk/test/Object/Inputs/macho-invalid-symtab-overlap (with props)
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=285632&r1=285631&r2=285632&view=diff
==============================================================================
--- llvm/trunk/lib/Object/MachOObjectFile.cpp (original)
+++ llvm/trunk/lib/Object/MachOObjectFile.cpp Mon Oct 31 15:29:48 2016
@@ -27,6 +27,7 @@
#include <cctype>
#include <cstring>
#include <limits>
+#include <list>
using namespace llvm;
using namespace object;
@@ -216,6 +217,42 @@ static void parseHeader(const MachOObjec
Err = HeaderOrErr.takeError();
}
+// This is used to check for overlapping of Mach-O elements.
+struct MachOElement {
+ uint64_t Offset;
+ uint64_t Size;
+ const char *Name;
+};
+
+static Error checkOverlappingElement(std::list<MachOElement> &Elements,
+ uint64_t Offset, uint64_t Size,
+ const char *Name) {
+ if (Size == 0)
+ return Error::success();
+
+ for (auto it=Elements.begin() ; it != Elements.end(); ++it) {
+ auto E = *it;
+ if ((Offset >= E.Offset && Offset < E.Offset + E.Size) ||
+ (Offset + Size > E.Offset && Offset + Size < E.Offset + E.Size) ||
+ (Offset <= E.Offset && Offset + Size >= E.Offset + E.Size))
+ return malformedError(Twine(Name) + " at offset " + Twine(Offset) +
+ " with a size of " + Twine(Size) + ", overlaps " +
+ E.Name + " at offset " + Twine(E.Offset) + " with "
+ "a size of " + Twine(E.Size));
+ auto nt = it;
+ nt++;
+ if (nt != Elements.end()) {
+ auto N = *nt;
+ if (Offset + Size <= N.Offset) {
+ Elements.insert(nt, {Offset, Size, Name});
+ return Error::success();
+ }
+ }
+ }
+ Elements.push_back({Offset, Size, Name});
+ return Error::success();
+}
+
// Parses LC_SEGMENT or LC_SEGMENT_64 load command, adds addresses of all
// sections to \param Sections, and optionally sets
// \param IsPageZeroSegment to true.
@@ -331,7 +368,8 @@ static Error parseSegmentLoadCommand(
static Error checkSymtabCommand(const MachOObjectFile *Obj,
const MachOObjectFile::LoadCommandInfo &Load,
uint32_t LoadCommandIndex,
- const char **SymtabLoadCmd) {
+ const char **SymtabLoadCmd,
+ std::list<MachOElement> &Elements) {
if (Load.C.cmdsize < sizeof(MachO::symtab_command))
return malformedError("load command " + Twine(LoadCommandIndex) +
" LC_SYMTAB cmdsize too small");
@@ -347,21 +385,25 @@ static Error checkSymtabCommand(const Ma
return malformedError("symoff field of LC_SYMTAB command " +
Twine(LoadCommandIndex) + " extends past the end "
"of the file");
- uint64_t BigSize = Symtab.nsyms;
+ uint64_t SymtabSize = Symtab.nsyms;
const char *struct_nlist_name;
if (Obj->is64Bit()) {
- BigSize *= sizeof(MachO::nlist_64);
+ SymtabSize *= sizeof(MachO::nlist_64);
struct_nlist_name = "struct nlist_64";
} else {
- BigSize *= sizeof(MachO::nlist);
+ SymtabSize *= sizeof(MachO::nlist);
struct_nlist_name = "struct nlist";
}
+ uint64_t BigSize = SymtabSize;
BigSize += Symtab.symoff;
if (BigSize > FileSize)
return malformedError("symoff field plus nsyms field times sizeof(" +
Twine(struct_nlist_name) + ") of LC_SYMTAB command " +
Twine(LoadCommandIndex) + " extends past the end "
"of the file");
+ if (Error Err = checkOverlappingElement(Elements, Symtab.symoff, SymtabSize,
+ "symbol table"))
+ return Err;
if (Symtab.stroff > FileSize)
return malformedError("stroff field of LC_SYMTAB command " +
Twine(LoadCommandIndex) + " extends past the end "
@@ -372,6 +414,9 @@ static Error checkSymtabCommand(const Ma
return malformedError("stroff field plus strsize field of LC_SYMTAB "
"command " + Twine(LoadCommandIndex) + " extends "
"past the end of the file");
+ if (Error Err = checkOverlappingElement(Elements, Symtab.stroff,
+ Symtab.strsize, "string table"))
+ return Err;
*SymtabLoadCmd = Load.Ptr;
return Error::success();
}
@@ -977,6 +1022,8 @@ MachOObjectFile::MachOObjectFile(MemoryB
"object file's mach header");
return;
}
+ std::list<MachOElement> Elements;
+ Elements.push_back({0, SizeOfHeaders, "Mach-O headers"});
uint32_t LoadCommandCount = getHeader().ncmds;
LoadCommandInfo Load;
@@ -1023,7 +1070,7 @@ MachOObjectFile::MachOObjectFile(MemoryB
}
LoadCommands.push_back(Load);
if (Load.C.cmd == MachO::LC_SYMTAB) {
- if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd)))
+ if ((Err = checkSymtabCommand(this, Load, I, &SymtabLoadCmd, Elements)))
return;
} else if (Load.C.cmd == MachO::LC_DYSYMTAB) {
if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd)))
Added: llvm/trunk/test/Object/Inputs/macho-invalid-strtab-overlap
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Inputs/macho-invalid-strtab-overlap?rev=285632&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/test/Object/Inputs/macho-invalid-strtab-overlap
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Added: llvm/trunk/test/Object/Inputs/macho-invalid-symtab-overlap
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/Inputs/macho-invalid-symtab-overlap?rev=285632&view=auto
==============================================================================
Binary file - no diff available.
Propchange: llvm/trunk/test/Object/Inputs/macho-invalid-symtab-overlap
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: llvm/trunk/test/Object/macho-invalid.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Object/macho-invalid.test?rev=285632&r1=285631&r2=285632&view=diff
==============================================================================
--- llvm/trunk/test/Object/macho-invalid.test (original)
+++ llvm/trunk/test/Object/macho-invalid.test Mon Oct 31 15:29:48 2016
@@ -433,3 +433,9 @@ INVALID-FVMFILE-OBSOLETE: macho-invalid-
RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-prepage-obsolete 2>&1 | FileCheck -check-prefix INVALID-PREPAGE-OBSOLETE %s
INVALID-PREPAGE-OBSOLETE: macho-invalid-prepage-obsolete': truncated or malformed object (load command 0 for cmd value of: 10 is obsolete and not supported)
+
+RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-symtab-overlap 2>&1 | FileCheck -check-prefix INVALID-SYMTAB-OVERLAP %s
+INVALID-SYMTAB-OVERLAP: macho-invalid-symtab-overlap': truncated or malformed object (symbol table at offset 8 with a size of 12, overlaps Mach-O headers at offset 0 with a size of 52)
+
+RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-strtab-overlap 2>&1 | FileCheck -check-prefix INVALID-STRTAB-OVERLAP %s
+INVALID-STRTAB-OVERLAP: macho-invalid-strtab-overlap': truncated or malformed object (string table at offset 60 with a size of 16, overlaps symbol table at offset 52 with a size of 12)
More information about the llvm-commits
mailing list