Mach unpack checks for bad load_command in compressed input

https://github.com/upx/upx/issues/564
	modified:   p_mach.cpp
This commit is contained in:
John Reiser 2022-02-25 10:17:04 -08:00 committed by Markus F.X.J. Oberhumer
parent 651155c64d
commit f204670008

View File

@ -1507,25 +1507,27 @@ void PackMachBase<T>::unpack(OutputFile *fo)
|| mhdri.filetype != mhdr->filetype) || mhdri.filetype != mhdr->filetype)
throwCantUnpack("file header corrupted"); throwCantUnpack("file header corrupted");
unsigned const ncmds = mhdr->ncmds; unsigned const ncmds = mhdr->ncmds;
if (!ncmds || 24 < ncmds) { // arbitrary limit if (!ncmds || 24 < ncmds) { // arbitrary limit
char msg[40]; snprintf(msg, sizeof(msg), char msg[40]; snprintf(msg, sizeof(msg),
"bad Mach_header.ncmds = %d", ncmds); "bad Mach_header.ncmds = %d", ncmds);
throwCantUnpack(msg); throwCantUnpack(msg);
} }
msegcmd_buf.alloc(sizeof(Mach_segment_command) * ncmds); msegcmd_buf.alloc(sizeof(Mach_segment_command) * ncmds);
msegcmd = (Mach_segment_command *)msegcmd_buf.getVoidPtr(); msegcmd = (Mach_segment_command *)msegcmd_buf.getVoidPtr();
unsigned char const *ptr = (unsigned char const *)(1+mhdr); unsigned char const *ptr = (unsigned char const *)(1+mhdr);
unsigned headway = mhdr_buf.getSize() - sizeof(*mhdr);
for (unsigned j= 0; j < ncmds; ++j) { for (unsigned j= 0; j < ncmds; ++j) {
unsigned char const *const next = ((Mach_command const *)ptr)->cmdsize + ptr; unsigned cmdsize = ((Mach_command const *)ptr)->cmdsize;
if (ptr_udiff(next, (1+ mhdr)) > ph.u_len) { if (is_bad_linker_command( ((Mach_command const *)ptr)->cmd, cmdsize,
char msg[50]; snprintf(msg, sizeof(msg), "cmdsize[%d] %#x", headway, lc_seg, sizeof(Addr))) {
j, (unsigned)(next - ptr)); char msg[50]; snprintf(msg, sizeof(msg),
"bad packed Mach load_command @%#x", ptr_udiff(ptr, mhdr));
throwCantUnpack(msg); throwCantUnpack(msg);
} }
memcpy(&msegcmd[j], ptr, umin(sizeof(Mach_segment_command), memcpy(&msegcmd[j], ptr, umin(sizeof(Mach_segment_command), cmdsize));
((Mach_command const *)ptr)->cmdsize)); headway -= cmdsize;
ptr = next; ptr += cmdsize;
} }
// Put LC_SEGMENT together at the beginning // Put LC_SEGMENT together at the beginning