mirror of
https://github.com/RPCSX/llvm.git
synced 2025-01-23 12:45:47 +00:00
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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@285632 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7e057dcd4e
commit
e9885e072b
@ -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 MachOObjectFile *Obj, T &Header,
|
||||
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 MachOObjectFile *Obj,
|
||||
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 MachOObjectFile *Obj,
|
||||
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(MemoryBufferRef Object, bool IsLittleEndian,
|
||||
"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(MemoryBufferRef Object, bool IsLittleEndian,
|
||||
}
|
||||
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)))
|
||||
|
BIN
test/Object/Inputs/macho-invalid-strtab-overlap
Normal file
BIN
test/Object/Inputs/macho-invalid-strtab-overlap
Normal file
Binary file not shown.
BIN
test/Object/Inputs/macho-invalid-symtab-overlap
Normal file
BIN
test/Object/Inputs/macho-invalid-symtab-overlap
Normal file
Binary file not shown.
@ -433,3 +433,9 @@ INVALID-FVMFILE-OBSOLETE: macho-invalid-fvmfile-obsolete': truncated or malforme
|
||||
|
||||
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)
|
||||
|
Loading…
x
Reference in New Issue
Block a user