1
0
mirror of https://github.com/upx/upx.git synced 2025-08-11 22:52:30 +08:00

Detect too-short Mach_command, also be careful in recovery

fuzzing from leon.weiss AT @ruhr-uni-bochum.de
https://github.com/upx/upx/issues/875
https://github.com/upx/upx/issues/874
	modified:   p_mach.cpp
This commit is contained in:
John Reiser
2025-01-31 11:34:48 -08:00
committed by Markus F.X.J. Oberhumer
parent 7b06ba0b78
commit a49d023bd0

View File

@ -1678,6 +1678,12 @@ tribool PackMachBase<T>::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) {
if (headway < (int)sizeof(Mach_command)) {
char buf[200]; snprintf(buf, sizeof(buf),
"bad Mach_command[%u]{@0x%zx,+0x%x}",
j, (sizeof(mhdri) + ((char const *)ptr - (char const *)rawmseg)), headway);
throwCantPack(buf);
}
unsigned const cmd = ptr->cmd;
unsigned const cmdsize = ptr->cmdsize;
if (is_bad_linker_command(cmd, cmdsize, headway, lc_seg, sizeof(Addr))) {
@ -1769,7 +1775,8 @@ tribool PackMachBase<T>::canUnpack()
fi->seek(offLINK - bufsize, SEEK_SET);
}
MemBuffer buf(bufsize);
MemBuffer buf3(bufsize);
MemBuffer buf3(upx::max(bufsize, 0x1008u));
buf3.clear();
fi->readx(buf, bufsize);
// Do not overwrite buf[]; For scratch space, then use buf3 instead.
@ -1882,9 +1889,13 @@ tribool PackMachBase<T>::canUnpack()
unsigned const *p;
for (p = (unsigned const *)&buf3[0x1000]; p > lo; ) if (*--p) {
overlay_offset = *(TE32 const *)p;
if ((unsigned)file_size < (overlay_offset + sizeof(PackHeader) + sizeof(overlay_offset)))
throwCantUnpack("file corrupted");
if ((off_t)overlay_offset < offLINK) {
overlay_offset = ((char const *)p - (char const *)lo) +
(offLINK - 0x1000) - overlay_offset + sizeof(l_info);
if ((unsigned)file_size < (overlay_offset + sizeof(PackHeader) + sizeof(overlay_offset)))
throwCantUnpack("file corrupted");
fi->seek(overlay_offset, SEEK_SET);
fi->readx(buf3, bufsize);
if (b_ptr->sz_unc < 0x4000
@ -1985,6 +1996,12 @@ tribool PackMachBase<T>::canPack()
unsigned char const *ptr = (unsigned char const *)rawmseg;
for (unsigned j= 0; j < ncmds; ++j) {
Mach_segment_command const *segptr = (Mach_segment_command const *)ptr;
if (headway < sizeof(Mach_command)) {
char buf[200]; snprintf(buf, sizeof(buf),
"bad Mach_command[%u]{@0x%zx,+0x%x}",
j, (sizeof(mhdri) + ((char const *)segptr - (char const *)rawmseg)), headway);
throwCantPack(buf);
}
unsigned const cmd = segptr->cmd &~ LC_REQ_DYLD;
unsigned const cmdsize = segptr->cmdsize;
if (is_bad_linker_command(cmd, cmdsize, headway, lc_seg, sizeof(Addr))) {