forked from OSchip/llvm-project
Next set of additional error checks for invalid Mach-O files for bad load commands
that use the Mach::linkedit_data_command type for the load commands that are currently used in the MachOObjectFile constructor. This contains the missing checks for LC_DATA_IN_CODE and LC_LINKER_OPTIMIZATION_HINT load commands and the fields for the Mach::linkedit_data_command type. Checking for other load commands that use this type will be added later. Also fixed a couple of places that was using sizeof(MachOObjectFile::LoadCommandInfo) that should have been using sizeof(MachO::load_command). llvm-svn: 280267
This commit is contained in:
parent
2700bd831a
commit
9d0c945ad6
|
@ -184,7 +184,7 @@ static Expected<MachOObjectFile::LoadCommandInfo>
|
|||
getFirstLoadCommandInfo(const MachOObjectFile *Obj) {
|
||||
unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
|
||||
: sizeof(MachO::mach_header);
|
||||
if (sizeof(MachOObjectFile::LoadCommandInfo) > Obj->getHeader().sizeofcmds)
|
||||
if (sizeof(MachO::load_command) > Obj->getHeader().sizeofcmds)
|
||||
return malformedError("load command 0 extends past the end all load "
|
||||
"commands in the file");
|
||||
return getLoadCommandInfo(Obj, getPtr(Obj, HeaderSize), 0);
|
||||
|
@ -195,7 +195,7 @@ getNextLoadCommandInfo(const MachOObjectFile *Obj, uint32_t LoadCommandIndex,
|
|||
const MachOObjectFile::LoadCommandInfo &L) {
|
||||
unsigned HeaderSize = Obj->is64Bit() ? sizeof(MachO::mach_header_64)
|
||||
: sizeof(MachO::mach_header);
|
||||
if (L.Ptr + L.C.cmdsize + sizeof(MachOObjectFile::LoadCommandInfo) >
|
||||
if (L.Ptr + L.C.cmdsize + sizeof(MachO::load_command) >
|
||||
Obj->getData().data() + HeaderSize + Obj->getHeader().sizeofcmds)
|
||||
return malformedError("load command " + Twine(LoadCommandIndex + 1) +
|
||||
" extends past the end all load commands in the file");
|
||||
|
@ -474,6 +474,36 @@ static Error checkDysymtabCommand(const MachOObjectFile *Obj,
|
|||
return Error::success();
|
||||
}
|
||||
|
||||
static Error checkLinkeditDataCommand(const MachOObjectFile *Obj,
|
||||
const MachOObjectFile::LoadCommandInfo &Load,
|
||||
uint32_t LoadCommandIndex,
|
||||
const char **LoadCmd, const char *CmdName) {
|
||||
if (Load.C.cmdsize < sizeof(MachO::linkedit_data_command))
|
||||
return malformedError("load command " + Twine(LoadCommandIndex) + " " +
|
||||
CmdName + " cmdsize too small");
|
||||
if (*LoadCmd != nullptr)
|
||||
return malformedError("more than one " + Twine(CmdName) + " command");
|
||||
MachO::linkedit_data_command LinkData =
|
||||
getStruct<MachO::linkedit_data_command>(Obj, Load.Ptr);
|
||||
if (LinkData.cmdsize != sizeof(MachO::linkedit_data_command))
|
||||
return malformedError(Twine(CmdName) + " command " +
|
||||
Twine(LoadCommandIndex) + " has incorrect cmdsize");
|
||||
uint64_t FileSize = Obj->getData().size();
|
||||
if (LinkData.dataoff > FileSize)
|
||||
return malformedError("dataoff field of " + Twine(CmdName) + " command " +
|
||||
Twine(LoadCommandIndex) + " extends past the end of "
|
||||
"the file");
|
||||
uint64_t BigSize = LinkData.dataoff;
|
||||
BigSize += LinkData.datasize;
|
||||
if (BigSize > FileSize)
|
||||
return malformedError("dataoff field plus datasize field of " +
|
||||
Twine(CmdName) + " command " +
|
||||
Twine(LoadCommandIndex) + " extends past the end of "
|
||||
"the file");
|
||||
*LoadCmd = Load.Ptr;
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<MachOObjectFile>>
|
||||
MachOObjectFile::create(MemoryBufferRef Object, bool IsLittleEndian,
|
||||
bool Is64Bits) {
|
||||
|
@ -550,19 +580,13 @@ MachOObjectFile::MachOObjectFile(MemoryBufferRef Object, bool IsLittleEndian,
|
|||
if ((Err = checkDysymtabCommand(this, Load, I, &DysymtabLoadCmd)))
|
||||
return;
|
||||
} else if (Load.C.cmd == MachO::LC_DATA_IN_CODE) {
|
||||
// Multiple data in code tables
|
||||
if (DataInCodeLoadCmd) {
|
||||
Err = malformedError("Multiple data-in-code tables");
|
||||
if ((Err = checkLinkeditDataCommand(this, Load, I, &DataInCodeLoadCmd,
|
||||
"LC_DATA_IN_CODE")))
|
||||
return;
|
||||
}
|
||||
DataInCodeLoadCmd = Load.Ptr;
|
||||
} else if (Load.C.cmd == MachO::LC_LINKER_OPTIMIZATION_HINT) {
|
||||
// Multiple linker optimization hint tables
|
||||
if (LinkOptHintsLoadCmd) {
|
||||
Err = malformedError("Multiple linker optimization hint tables");
|
||||
if ((Err = checkLinkeditDataCommand(this, Load, I, &LinkOptHintsLoadCmd,
|
||||
"LC_LINKER_OPTIMIZATION_HINT")))
|
||||
return;
|
||||
}
|
||||
LinkOptHintsLoadCmd = Load.Ptr;
|
||||
} else if (Load.C.cmd == MachO::LC_DYLD_INFO ||
|
||||
Load.C.cmd == MachO::LC_DYLD_INFO_ONLY) {
|
||||
// Multiple dyldinfo load commands
|
||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -208,3 +208,19 @@ INVALID-DYSYMTAB-TOCOFF-LOCRELOFF: macho-invalid-dysymtab-locreloff': truncated
|
|||
|
||||
RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dysymtab-locreloff-nlocrel 2>&1 | FileCheck -check-prefix INVALID-DYSYMTAB-TOCOFF-LOCRELOFF-NLOCREL %s
|
||||
INVALID-DYSYMTAB-TOCOFF-LOCRELOFF-NLOCREL: macho-invalid-dysymtab-locreloff-nlocrel': truncated or malformed object (locreloff field plus nlocrel field times sizeof(struct relocation_info) of LC_DYSYMTAB command 0 extends past the end of the file)
|
||||
|
||||
RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dataincode-more-than-one 2>&1 | FileCheck -check-prefix INVALID-DATAINCODE-MORE-THAN-ONE %s
|
||||
INVALID-DATAINCODE-MORE-THAN-ONE: macho-invalid-dataincode-more-than-one': truncated or malformed object (more than one LC_DATA_IN_CODE command)
|
||||
|
||||
RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-linkopthint-small 2>&1 | FileCheck -check-prefix INVALID-LINKOPTHINT-SMALL %s
|
||||
INVALID-LINKOPTHINT-SMALL: macho-invalid-linkopthint-small': truncated or malformed object (load command 0 LC_LINKER_OPTIMIZATION_HINT cmdsize too small)
|
||||
|
||||
RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dataincode-bad-size 2>&1 | FileCheck -check-prefix INVALID-DATAINCODE-BAD-SIZE %s
|
||||
INVALID-DATAINCODE-BAD-SIZE: macho-invalid-dataincode-bad-size': truncated or malformed object (LC_DATA_IN_CODE command 0 has incorrect cmdsize)
|
||||
|
||||
RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-linkopthint-dataoff 2>&1 | FileCheck -check-prefix INVALID-LINKOPTHINT-DATAOFF %s
|
||||
INVALID-LINKOPTHINT-DATAOFF: macho-invalid-linkopthint-dataoff': truncated or malformed object (dataoff field of LC_LINKER_OPTIMIZATION_HINT command 0 extends past the end of the file)
|
||||
|
||||
RUN: not llvm-objdump -macho -private-headers %p/Inputs/macho-invalid-dataincode-dataoff-datasize 2>&1 | FileCheck -check-prefix INVALID-DATAINCODE-DATAOFF-DATASIZE %s
|
||||
INVALID-DATAINCODE-DATAOFF-DATASIZE: macho-invalid-dataincode-dataoff-datasize': truncated or malformed object (dataoff field plus datasize field of LC_DATA_IN_CODE command 0 extends past the end of the file)
|
||||
|
||||
|
|
Loading…
Reference in New Issue