From 819c33fee2b2c33b96bef27a13cb20f2589819aa Mon Sep 17 00:00:00 2001 From: John Reiser Date: Fri, 15 Nov 2019 21:32:06 -0800 Subject: [PATCH] Detect malformed Mach-o file in ::canUnpack() https://github.com/upx/upx/issues/314 https://github.com/upx/upx/issues/315 modified: p_mach.cpp --- src/p_mach.cpp | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/p_mach.cpp b/src/p_mach.cpp index 2c074d92..fe7b20f9 100644 --- a/src/p_mach.cpp +++ b/src/p_mach.cpp @@ -1518,8 +1518,13 @@ int PackMachBase::canUnpack() my_cpusubtype = mhdri.cpusubtype; int headway = (int)mhdri.sizeofcmds; + if (headway < (int)(3 * sizeof(Mach_segment_command) + + sizeof(Mach_main_command))) { + infoWarning("Mach_header.sizeofcmds = %d too small", headway); + throwCantUnpack("file corrupted"); + } sz_mach_headers = headway + sizeof(mhdri); - if (1024 < headway) { + if (2048 < headway) { infoWarning("Mach_header.sizeofcmds(%d) > 1024", headway); } rawmseg = (Mach_segment_command *) New(char, mhdri.sizeofcmds); @@ -1535,8 +1540,24 @@ int PackMachBase::canUnpack() Mach_command const *ptr = (Mach_command const *)rawmseg; for (unsigned j= 0; j < ncmds; ptr = (Mach_command const *)(ptr->cmdsize + (char const *)ptr), ++j) { - Mach_segment_command const *const segptr = (Mach_segment_command const *)ptr; + if ((unsigned)headway < ptr->cmdsize) { + infoWarning("bad Mach_command[%u]{@0x%lx,+0x%x}: file_size=0x%lx cmdsize=0x%lx", + j, sizeof(mhdri) + ((char const *)ptr - (char const *)rawmseg), headway, + file_size, (unsigned long)ptr->cmdsize); + throwCantUnpack("file corrupted"); + } if (lc_seg == ptr->cmd) { + Mach_segment_command const *const segptr = (Mach_segment_command const *)ptr; + if ((unsigned long)file_size < segptr->filesize + || (unsigned long)file_size < segptr->fileoff + || (unsigned long)file_size < (segptr->filesize + segptr->fileoff)) { + infoWarning("bad Mach_segment_command[%u]{@0x%lx,+0x%x}: file_size=0x%lx cmdsize=0x%lx" + " filesize=0x%lx fileoff=0x%lx", + j, sizeof(mhdri) + ((char const *)ptr - (char const *)rawmseg), headway, + file_size, (unsigned long)ptr->cmdsize, + (unsigned long)segptr->filesize, (unsigned long)segptr->fileoff); + throwCantUnpack("file corrupted"); + } ++nseg; if (!strcmp("__XHDR", segptr->segname)) { // PackHeader precedes __LINKEDIT (pre-Sierra MacOS 10.12)