File 0001-Mach-o-defend-against-bad-crafted-input.patch of Package upx
From 6eafa552bb4bf2303fbadf1f65e7d99919d476c6 Mon Sep 17 00:00:00 2001
From: John Reiser <jreiser@BitWagon.com>
X-From: did conflict resolution for applying to 3.94.0, <jengelh@inai.de>
Date: Wed, 15 Nov 2017 13:38:54 -0800
Subject: [PATCH] Mach-o defend against bad crafted input
https://github.com/upx/upx/issues/146
modified: p_mach.cpp
---
src/p_mach.cpp | 17 +++++++++++++++--
1 file changed, 15 insertions(+), 2 deletions(-)
Index: upx-3.94-src/src/p_mach.cpp
===================================================================
--- upx-3.94-src.orig/src/p_mach.cpp
+++ upx-3.94-src/src/p_mach.cpp
@@ -1835,6 +1835,12 @@ bool PackMachBase<T>::canPack()
return false;
my_cpusubtype = mhdri.cpusubtype;
+ unsigned int szx = mhdri.sizeofcmds;
+ unsigned headway = file_size - sizeof(mhdri);
+ if (headway < szx) {
+ char buf[32]; snprintf(buf, sizeof(buf), "bad sizeofcmds %u", szx);
+ throwCantPack(buf);
+ }
rawmseg = (Mach_segment_command *)new char[(unsigned) mhdri.sizeofcmds];
fi->readx(rawmseg, mhdri.sizeofcmds);
@@ -1843,11 +1849,18 @@ bool 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 < ((Mach_command const *)ptr)->cmdsize) {
+ char buf[64]; snprintf(buf, sizeof(buf),
+ "bad Mach_command[%d]{%#x, %#x}", j,
+ (unsigned)segptr->cmd, (unsigned)((Mach_command const *)ptr)->cmdsize);
+ throwCantPack(buf);
+ }
+ headway -= ((Mach_command const *)ptr)->cmdsize;
if (lc_seg == segptr->cmd) {
msegcmd[j] = *segptr;
}
else {
- memcpy(&msegcmd[j], ptr, 2*sizeof(unsigned)); // cmd and size
+ memcpy(&msegcmd[j], ptr, 2*sizeof(unsigned)); // cmd and cmdsize
}
switch (((Mach_uuid_command const *)ptr)->cmd) {
default: break;
@@ -1872,7 +1885,7 @@ bool PackMachBase<T>::canPack()
prev_init_address =
((Mach_routines_command const *)ptr)->init_address;
}
- ptr += (unsigned) ((const Mach_segment_command *)ptr)->cmdsize;
+ ptr += (unsigned) ((Mach_command const *)ptr)->cmdsize;
}
if (Mach_header::MH_DYLIB==my_filetype && 0==o_routines_cmd) {
infoWarning("missing -init function");