mirror of
https://github.com/radareorg/radare2.git
synced 2025-01-24 23:06:36 +00:00
Fix #12384 - Crash in fuzzed macho binary
This commit is contained in:
parent
df167c7db5
commit
df90a3c462
@ -2003,7 +2003,7 @@ struct import_t* MACH0_(get_imports)(struct MACH0_(obj_t)* bin) {
|
||||
}
|
||||
|
||||
struct reloc_t* MACH0_(get_relocs)(struct MACH0_(obj_t)* bin) {
|
||||
struct reloc_t *relocs;
|
||||
struct reloc_t *relocs = NULL;
|
||||
int i = 0, len;
|
||||
ulebr ur = {NULL};
|
||||
int wordsize = MACH0_(get_bits)(bin) / 8;
|
||||
@ -2046,24 +2046,26 @@ struct reloc_t* MACH0_(get_relocs)(struct MACH0_(obj_t)* bin) {
|
||||
return NULL;
|
||||
}
|
||||
// NOTE(eddyb) it's a waste of memory, but we don't know the actual number of relocs.
|
||||
if (!(relocs = calloc (1, (1 + bind_size + lazy_size) * sizeof (struct reloc_t)))) {
|
||||
int amount = bind_size + lazy_size;
|
||||
if (amount < 0) {
|
||||
amount = 0;
|
||||
}
|
||||
if (!(relocs = calloc (amount + 1, sizeof (struct reloc_t)))) {
|
||||
return NULL;
|
||||
}
|
||||
opcodes = calloc (1, bind_size + lazy_size + 1);
|
||||
opcodes = calloc (1, amount + 1);
|
||||
if (!opcodes) {
|
||||
free (relocs);
|
||||
return NULL;
|
||||
}
|
||||
len = r_buf_read_at (bin->b, bin->dyld_info->bind_off, opcodes, bind_size);
|
||||
i = r_buf_read_at (bin->b, bin->dyld_info->lazy_bind_off, opcodes + bind_size, lazy_size);
|
||||
if (len < 1 || i < 1) {
|
||||
bprintf ("Error: read (dyld_info bind) at 0x%08"PFMT64x"\n",
|
||||
(ut64)(size_t)bin->dyld_info->bind_off);
|
||||
int ls = r_buf_read_at (bin->b, bin->dyld_info->lazy_bind_off, opcodes + bind_size, lazy_size);
|
||||
if (len < 1 || ls < 1) {
|
||||
bprintf ("Error: read (dyld_info bind) at 0x%08"PFMT64x"\n", (ut64)(size_t)bin->dyld_info->bind_off);
|
||||
free (opcodes);
|
||||
relocs[i].last = 1;
|
||||
relocs[i].last = true;
|
||||
return relocs;
|
||||
}
|
||||
i = 0;
|
||||
// that +2 is a minimum required for uleb128, this may be wrong,
|
||||
// the correct fix would be to make ULEB() must use rutil's
|
||||
// implementation that already checks for buffer boundaries
|
||||
@ -2126,7 +2128,7 @@ struct reloc_t* MACH0_(get_relocs)(struct MACH0_(obj_t)* bin) {
|
||||
bprintf ("Error: BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB"
|
||||
" has unexistent segment %d\n", seg_idx);
|
||||
addr = 0LL;
|
||||
free (relocs);
|
||||
R_FREE (relocs);
|
||||
return 0; // early exit to avoid future mayhem
|
||||
} else {
|
||||
addr = bin->segs[seg_idx].vmaddr + ULEB();
|
||||
@ -2156,7 +2158,7 @@ relocs[i++].last = 0;\
|
||||
bprintf ("Error: Malformed DO bind opcode\n");
|
||||
goto beach;
|
||||
}
|
||||
DO_BIND();
|
||||
DO_BIND ();
|
||||
addr += wordsize;
|
||||
break;
|
||||
case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
|
||||
@ -2164,8 +2166,8 @@ relocs[i++].last = 0;\
|
||||
bprintf ("Error: Malformed ADDR ULEB bind opcode\n");
|
||||
goto beach;
|
||||
}
|
||||
DO_BIND();
|
||||
addr += ULEB() + wordsize;
|
||||
DO_BIND ();
|
||||
addr += ULEB () + wordsize;
|
||||
break;
|
||||
case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
|
||||
if (addr >= segmentAddress) {
|
||||
@ -2173,7 +2175,7 @@ relocs[i++].last = 0;\
|
||||
goto beach;
|
||||
}
|
||||
DO_BIND();
|
||||
addr += (ut64)imm * (ut64)wordsize + wordsize;
|
||||
addr += (ut64)imm * (ut64)(wordsize + wordsize);
|
||||
break;
|
||||
case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
|
||||
count = ULEB();
|
||||
@ -2183,7 +2185,7 @@ relocs[i++].last = 0;\
|
||||
bprintf ("Error: Malformed ULEB TIMES bind opcode\n");
|
||||
goto beach;
|
||||
}
|
||||
DO_BIND();
|
||||
DO_BIND ();
|
||||
addr += skip + wordsize;
|
||||
}
|
||||
break;
|
||||
@ -2203,10 +2205,15 @@ relocs[i++].last = 0;\
|
||||
if (!bin->symtab || !bin->symstr || !bin->sects || !bin->indirectsyms) {
|
||||
return NULL;
|
||||
}
|
||||
if (!(relocs = malloc ((bin->dysymtab.nundefsym + 1) * sizeof (struct reloc_t)))) {
|
||||
int amount = bin->dysymtab.nundefsym;
|
||||
if (amount < 0) {
|
||||
amount = 0;
|
||||
}
|
||||
free (relocs);
|
||||
if (!(relocs = calloc (amount + 1, sizeof (struct reloc_t)))) {
|
||||
return NULL;
|
||||
}
|
||||
for (j = 0; j < bin->dysymtab.nundefsym; j++) {
|
||||
for (j = 0; j < amount; j++) {
|
||||
if (parse_import_ptr (bin, &relocs[i], bin->dysymtab.iundefsym + j)) {
|
||||
relocs[i].ord = j;
|
||||
relocs[i++].last = 0;
|
||||
@ -2214,7 +2221,9 @@ relocs[i++].last = 0;\
|
||||
}
|
||||
}
|
||||
beach:
|
||||
relocs[i].last = 1;
|
||||
if (relocs) {
|
||||
relocs[i].last = 1;
|
||||
}
|
||||
return relocs;
|
||||
}
|
||||
|
||||
|
@ -2709,7 +2709,6 @@ static RList *recurse_bb(RCore *core, ut64 addr, RAnalBlock *dest) {
|
||||
}
|
||||
|
||||
R_API void r_core_recover_vars(RCore *core, RAnalFunction *fcn, bool argonly) {
|
||||
ut8 *buf;
|
||||
RListIter *tmp = NULL;
|
||||
RAnalBlock *bb = NULL;
|
||||
RAnalOp *op = NULL;
|
||||
@ -2721,7 +2720,7 @@ R_API void r_core_recover_vars(RCore *core, RAnalFunction *fcn, bool argonly) {
|
||||
return;
|
||||
}
|
||||
int bb_size = core->anal->opt.bb_max_size;
|
||||
buf = calloc (1, bb_size);
|
||||
ut8 *buf = calloc (1, bb_size);
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user