Better checking of Mach_header.ncmds, .sizeofcmds
Improves earlier fix. https://github.com/upx/upx/issues/447 modified: p_mach.cpp
This commit is contained in:
committed by
Markus F.X.J. Oberhumer
parent
f17d9967c2
commit
21d102c84f
+10
-7
@@ -1532,11 +1532,15 @@ int PackMachBase<T>::canUnpack()
|
|||||||
return false;
|
return false;
|
||||||
my_cpusubtype = mhdri.cpusubtype;
|
my_cpusubtype = mhdri.cpusubtype;
|
||||||
|
|
||||||
|
unsigned const ncmds = mhdri.ncmds;
|
||||||
int headway = (int)mhdri.sizeofcmds;
|
int headway = (int)mhdri.sizeofcmds;
|
||||||
// old style: LC_SEGMENT + LC_UNIXTHREAD [smaller, varies by $ARCH]
|
// old style: LC_SEGMENT + LC_UNIXTHREAD [smaller, varies by $ARCH]
|
||||||
// new style: 3*LC_SEGMENT + LC_MAIN [larger]
|
// new style: 3*LC_SEGMENT + LC_MAIN [larger]
|
||||||
// FIXME: So this test is weak.
|
if ((2 == ncmds
|
||||||
if (headway < (int)(sizeof(Mach_segment_command) + 4*4)) {
|
&& 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);
|
infoWarning("Mach_header.sizeofcmds = %d too small", headway);
|
||||||
throwCantUnpack("file corrupted");
|
throwCantUnpack("file corrupted");
|
||||||
}
|
}
|
||||||
@@ -1554,7 +1558,6 @@ int PackMachBase<T>::canUnpack()
|
|||||||
off_t offLINK = 0;
|
off_t offLINK = 0;
|
||||||
unsigned pos_next = 0;
|
unsigned pos_next = 0;
|
||||||
unsigned nseg = 0;
|
unsigned nseg = 0;
|
||||||
unsigned const ncmds = mhdri.ncmds;
|
|
||||||
Mach_command const *ptr = (Mach_command const *)rawmseg;
|
Mach_command const *ptr = (Mach_command const *)rawmseg;
|
||||||
for (unsigned j= 0; j < ncmds;
|
for (unsigned j= 0; j < ncmds;
|
||||||
ptr = (Mach_command const *)(ptr->cmdsize + (char const *)ptr), ++j) {
|
ptr = (Mach_command const *)(ptr->cmdsize + (char const *)ptr), ++j) {
|
||||||
@@ -1805,6 +1808,10 @@ bool PackMachBase<T>::canPack()
|
|||||||
return false;
|
return false;
|
||||||
my_cpusubtype = mhdri.cpusubtype;
|
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 const sz_mhcmds = (unsigned)mhdri.sizeofcmds;
|
||||||
unsigned headway = file_size - sizeof(mhdri);
|
unsigned headway = file_size - sizeof(mhdri);
|
||||||
if (headway < sz_mhcmds) {
|
if (headway < sz_mhcmds) {
|
||||||
@@ -1819,10 +1826,6 @@ bool PackMachBase<T>::canPack()
|
|||||||
rawmseg = (Mach_segment_command *)(void *)rawmseg_buf;
|
rawmseg = (Mach_segment_command *)(void *)rawmseg_buf;
|
||||||
fi->readx(rawmseg, mhdri.sizeofcmds);
|
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_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 *)rawmseg;
|
unsigned char const *ptr = (unsigned char const *)rawmseg;
|
||||||
|
|||||||
Reference in New Issue
Block a user