diff --git a/src/p_mach.cpp b/src/p_mach.cpp index fa3b21d8..e0074bca 100644 --- a/src/p_mach.cpp +++ b/src/p_mach.cpp @@ -1532,11 +1532,15 @@ int PackMachBase::canUnpack() return false; my_cpusubtype = mhdri.cpusubtype; + unsigned const ncmds = mhdri.ncmds; int headway = (int)mhdri.sizeofcmds; // old style: LC_SEGMENT + LC_UNIXTHREAD [smaller, varies by $ARCH] // new style: 3*LC_SEGMENT + LC_MAIN [larger] - // FIXME: So this test is weak. - if (headway < (int)(sizeof(Mach_segment_command) + 4*4)) { + if ((2 == ncmds + && headway < (int)(sizeof(Mach_segment_command) + 4*4)) + || (3 <= ncmds + && headway < (int)(3 * sizeof(Mach_segment_command) + + sizeof(Mach_main_command)))) { infoWarning("Mach_header.sizeofcmds = %d too small", headway); throwCantUnpack("file corrupted"); } @@ -1554,7 +1558,6 @@ int PackMachBase::canUnpack() off_t offLINK = 0; unsigned pos_next = 0; unsigned nseg = 0; - unsigned const ncmds = mhdri.ncmds; Mach_command const *ptr = (Mach_command const *)rawmseg; for (unsigned j= 0; j < ncmds; ptr = (Mach_command const *)(ptr->cmdsize + (char const *)ptr), ++j) { @@ -1805,6 +1808,10 @@ bool PackMachBase::canPack() return false; my_cpusubtype = mhdri.cpusubtype; + unsigned const ncmds = mhdri.ncmds; + if (!ncmds || 256 < ncmds) { // arbitrary, but guard against garbage + throwCantPack("256 < Mach_header.ncmds"); + } unsigned const sz_mhcmds = (unsigned)mhdri.sizeofcmds; unsigned headway = file_size - sizeof(mhdri); if (headway < sz_mhcmds) { @@ -1819,10 +1826,6 @@ bool PackMachBase::canPack() rawmseg = (Mach_segment_command *)(void *)rawmseg_buf; fi->readx(rawmseg, mhdri.sizeofcmds); - unsigned const ncmds = mhdri.ncmds; - if (256 < ncmds) { // arbitrary, but guard against garbage - throwCantPack("256 < Mach_header.ncmds"); - } msegcmd_buf.alloc(sizeof(Mach_segment_command) * ncmds); msegcmd = (Mach_segment_command *)msegcmd_buf.getVoidPtr(); unsigned char const *ptr = (unsigned char const *)rawmseg;