Fix #17353 - Remove duplicated implementation of uleb128 in mach0 ##bin (#17489)

This commit is contained in:
phakeobj 2020-09-24 10:47:23 +03:00 committed by GitHub
parent ec6a52e8a9
commit 89e1618e3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 95 additions and 117 deletions

View File

@ -1083,7 +1083,7 @@ static VariableLocation *parse_dwarf_location (Context *ctx, const RBinDwarfAttr
/* I need to find binaries that uses this so I can test it out*/
const ut8 *buffer = &block.data[++i];
const ut8 *buf_end = &block.data[block.length];
buffer = r_uleb128 (buffer, buf_end - buffer, &reg_num);
buffer = r_uleb128 (buffer, buf_end - buffer, &reg_num, NULL);
if (buffer == buf_end) {
return NULL;
}

View File

@ -480,17 +480,17 @@ static const ut8 *parse_line_header_source(RBinFile *bf, const ut8 *buf, const u
buf = NULL;
goto beach;
}
buf = r_uleb128 (buf, buf_end - buf, &id_idx);
buf = r_uleb128 (buf, buf_end - buf, &id_idx, NULL);
if (buf >= buf_end) {
buf = NULL;
goto beach;
}
buf = r_uleb128 (buf, buf_end - buf, &mod_time);
buf = r_uleb128 (buf, buf_end - buf, &mod_time, NULL);
if (buf >= buf_end) {
buf = NULL;
goto beach;
}
buf = r_uleb128 (buf, buf_end - buf, &file_len);
buf = r_uleb128 (buf, buf_end - buf, &file_len, NULL);
if (buf >= buf_end) {
buf = NULL;
goto beach;
@ -779,17 +779,17 @@ static const ut8 *parse_ext_opcode(const RBin *bin, const ut8 *obuf,
ut64 dir_idx;
ut64 ignore;
if (buf + 1 < buf_end) {
buf = r_uleb128 (buf, buf_end - buf, &dir_idx);
buf = r_uleb128 (buf, buf_end - buf, &dir_idx, NULL);
}
if (buf + 1 < buf_end) {
buf = r_uleb128 (buf, buf_end - buf, &ignore);
buf = r_uleb128 (buf, buf_end - buf, &ignore, NULL);
}
if (buf + 1 < buf_end) {
buf = r_uleb128 (buf, buf_end - buf, &ignore);
buf = r_uleb128 (buf, buf_end - buf, &ignore, NULL);
}
break;
case DW_LNE_set_discriminator:
buf = r_uleb128 (buf, buf_end - buf, &addr);
buf = r_uleb128 (buf, buf_end - buf, &addr, NULL);
if (mode == R_MODE_PRINT) {
print ("set Discriminator to %"PFMT64d"\n", addr);
}
@ -887,7 +887,7 @@ static const ut8 *parse_std_opcode(
regs->basic_block = DWARF_FALSE;
break;
case DW_LNS_advance_pc:
buf = r_uleb128 (buf, buf_end - buf, &addr);
buf = r_uleb128 (buf, buf_end - buf, &addr, NULL);
regs->address += addr * hdr->min_inst_len;
if (mode == R_MODE_PRINT) {
print ("Advance PC by %"PFMT64d" to 0x%"PFMT64x"\n",
@ -902,14 +902,14 @@ static const ut8 *parse_std_opcode(
}
break;
case DW_LNS_set_file:
buf = r_uleb128 (buf, buf_end - buf, &addr);
buf = r_uleb128 (buf, buf_end - buf, &addr, NULL);
if (mode == R_MODE_PRINT) {
print ("Set file to %"PFMT64d"\n", addr);
}
regs->file = addr;
break;
case DW_LNS_set_column:
buf = r_uleb128 (buf, buf_end - buf, &addr);
buf = r_uleb128 (buf, buf_end - buf, &addr, NULL);
if (mode == R_MODE_PRINT) {
print ("Set column to %"PFMT64d"\n", addr);
}
@ -960,7 +960,7 @@ static const ut8 *parse_std_opcode(
}
break;
case DW_LNS_set_isa:
buf = r_uleb128 (buf, buf_end - buf, &addr);
buf = r_uleb128 (buf, buf_end - buf, &addr, NULL);
regs->isa = addr;
if (mode == R_MODE_PRINT) {
print ("set_isa\n");
@ -1654,7 +1654,7 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
break;
case DW_FORM_udata:
value->kind = DW_AT_KIND_CONSTANT;
buf = r_uleb128 (buf, buf_end - buf, &value->uconstant);
buf = r_uleb128 (buf, buf_end - buf, &value->uconstant, NULL);
break;
case DW_FORM_string:
value->kind = DW_AT_KIND_STRING;
@ -1686,7 +1686,7 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
break;
case DW_FORM_block: // variable length ULEB128
value->kind = DW_AT_KIND_BLOCK;
buf = r_uleb128 (buf, buf_end - buf, &value->block.length);
buf = r_uleb128 (buf, buf_end - buf, &value->block.length, NULL);
if (!buf || buf >= buf_end) {
return NULL;
}
@ -1733,7 +1733,7 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
case DW_FORM_ref_udata:
value->kind = DW_AT_KIND_REFERENCE;
// uleb128 is enough to fit into ut64?
buf = r_uleb128 (buf, buf_end - buf, &value->reference);
buf = r_uleb128 (buf, buf_end - buf, &value->reference, NULL);
value->reference += hdr->unit_offset;
break;
// offset in a section other than .debug_info or .debug_str
@ -1743,7 +1743,7 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
break;
case DW_FORM_exprloc:
value->kind = DW_AT_KIND_BLOCK;
buf = r_uleb128 (buf, buf_end - buf, &value->block.length);
buf = r_uleb128 (buf, buf_end - buf, &value->block.length, NULL);
if (!buf || buf >= buf_end) {
return NULL;
}
@ -1794,7 +1794,7 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
index into an array of addresses in the .debug_addr section.*/
case DW_FORM_addrx:
value->kind = DW_AT_KIND_ADDRESS;
buf = r_uleb128 (buf, buf_end - buf, &value->address);
buf = r_uleb128 (buf, buf_end - buf, &value->address, NULL);
break;
case DW_FORM_addrx1:
value->kind = DW_AT_KIND_ADDRESS;
@ -1838,7 +1838,7 @@ static const ut8 *parse_attr_value(const ut8 *obuf, int obuf_len,
// An index into the .debug_rnglists
case DW_FORM_rnglistx:
value->kind = DW_AT_KIND_ADDRESS;
buf = r_uleb128 (buf, buf_end - buf, &value->address);
buf = r_uleb128 (buf, buf_end - buf, &value->address, NULL);
break;
default:
eprintf ("Unknown DW_FORM 0x%02" PFMT64x "\n", def->attr_form);
@ -1919,7 +1919,7 @@ static const ut8 *parse_comp_unit(RBinDwarfDebugInfo *info, Sdb *sdb, const ut8
// DIE starts with ULEB128 with the abbreviation code
ut64 abbr_code;
buf = r_uleb128 (buf, buf_end - buf, &abbr_code);
buf = r_uleb128 (buf, buf_end - buf, &abbr_code, NULL);
if (abbr_code > abbrevs->count || !buf) { // something invalid
return NULL;
@ -2114,7 +2114,7 @@ static RBinDwarfDebugAbbrev *parse_abbrev_raw(const ut8 *obuf, size_t len) {
while (buf && buf+1 < buf_end) {
offset = buf - obuf;
buf = r_uleb128 (buf, (size_t)(buf_end-buf), &tmp);
buf = r_uleb128 (buf, (size_t)(buf_end-buf), &tmp, NULL);
if (!buf || !tmp || buf >= buf_end) {
continue;
}
@ -2125,7 +2125,7 @@ static RBinDwarfDebugAbbrev *parse_abbrev_raw(const ut8 *obuf, size_t len) {
init_abbrev_decl (tmpdecl);
tmpdecl->code = tmp;
buf = r_uleb128 (buf, (size_t)(buf_end-buf), &tmp);
buf = r_uleb128 (buf, (size_t)(buf_end-buf), &tmp, NULL);
tmpdecl->tag = tmp;
tmpdecl->offset = offset;
@ -2138,11 +2138,11 @@ static RBinDwarfDebugAbbrev *parse_abbrev_raw(const ut8 *obuf, size_t len) {
if (tmpdecl->count == tmpdecl->capacity) {
expand_abbrev_decl (tmpdecl);
}
buf = r_uleb128 (buf, (size_t)(buf_end - buf), &attr_code);
buf = r_uleb128 (buf, (size_t)(buf_end - buf), &attr_code, NULL);
if (buf >= buf_end) {
break;
}
buf = r_uleb128 (buf, (size_t)(buf_end - buf), &attr_form);
buf = r_uleb128 (buf, (size_t)(buf_end - buf), &attr_form, NULL);
// http://www.dwarfstd.org/doc/DWARF5.pdf#page=225
if (attr_form == DW_FORM_implicit_const) {
buf = r_leb128 (buf, (size_t)(buf_end - buf), &special);

View File

@ -10,10 +10,6 @@
#define bprintf if (bin->verbose) eprintf
#define Eprintf if (mo->verbose) eprintf
typedef struct _ulebr {
ut8 *p;
} ulebr;
typedef struct {
struct symbol_t *symbols;
int j;
@ -34,54 +30,16 @@ typedef struct {
// USE THIS: int ws = bf->o->info->big_endian;
#define mach0_endian 1
// TODO: Use the implementation from RUtil
static ut64 read_uleb128(ulebr *r, ut8 *end) {
ut64 result = 0;
int bit = 0;
ut64 slice = 0;
ut8 *p = r->p;
do {
if (p == end) {
eprintf ("malformed uleb128\n");
return UT64_MAX;
}
slice = *p & 0x7f;
if (bit > 63) {
eprintf ("uleb128 too big for uint64, bit=%d, result=0x%"PFMT64x"\n", bit, result);
return UT64_MAX;
} else {
result |= (slice << bit);
bit += 7;
}
} while (*p++ & 0x80);
r->p = p;
return result;
}
static st64 read_sleb128(ulebr *r, ut8 *end) {
st64 result = 0;
int bit = 0;
ut8 byte = 0;
ut8 *p = r->p;
do {
if (p == end) {
eprintf ("malformed sleb128\n");
break;
}
byte = *p++;
result |= (((st64)(byte & 0x7f)) << bit);
bit += 7;
if (bit > 63) {
eprintf ("too large sleb128 shift\n");
return result;
}
} while (byte & 0x80);
// sign extend negative numbers
if ((byte & 0x40)) {
result |= (-1LL) << bit;
static ut64 read_uleb128(ut8 **p, ut8 *end) {
const char *error = NULL;
ut64 v;
*p = (ut8 *)r_uleb128 (*p, end - *p, &v, &error);
if (error) {
eprintf (error);
R_FREE (error);
return UT64_MAX;
}
r->p = p;
return result;
return v;
}
static ut64 entry_to_vaddr(struct MACH0_(obj_t) *bin) {
@ -1588,7 +1546,7 @@ static bool reconstruct_chained_fixup(struct MACH0_(obj_t) *bin) {
return false;
}
size_t wordsize = get_word_size (bin);
ulebr ur = {NULL};
ut8 *p = NULL;
size_t j, count, skip, bind_size;
int seg_idx = 0;
ut64 seg_off = 0;
@ -1615,9 +1573,9 @@ static bool reconstruct_chained_fixup(struct MACH0_(obj_t) *bin) {
size_t cur_seg_idx = 0;
ut8 *end;
bool done = false;
for (ur.p = opcodes, end = opcodes + bind_size; !done && ur.p < end;) {
ut8 imm = *ur.p & BIND_IMMEDIATE_MASK, op = *ur.p & BIND_OPCODE_MASK;
ur.p++;
for (p = opcodes, end = opcodes + bind_size; !done && p < end;) {
ut8 imm = *p & BIND_IMMEDIATE_MASK, op = *p & BIND_OPCODE_MASK;
p++;
switch (op) {
case BIND_OPCODE_DONE:
done = true;
@ -1625,7 +1583,7 @@ static bool reconstruct_chained_fixup(struct MACH0_(obj_t) *bin) {
case BIND_OPCODE_THREADED: {
switch (imm) {
case BIND_SUBOPCODE_THREADED_SET_BIND_ORDINAL_TABLE_SIZE_ULEB: {
read_uleb128 (&ur, end);
read_uleb128 (&p, end);
break;
}
case BIND_SUBOPCODE_THREADED_APPLY: {
@ -1670,15 +1628,15 @@ static bool reconstruct_chained_fixup(struct MACH0_(obj_t) *bin) {
case BIND_OPCODE_SET_TYPE_IMM:
break;
case BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
read_uleb128 (&ur, end);
read_uleb128 (&p, end);
break;
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
while (*ur.p++ && ur.p < end) {
while (*p++ && p < end) {
/* empty loop */
}
break;
case BIND_OPCODE_SET_ADDEND_SLEB:
read_sleb128 (&ur, end);
r_sleb128 ((const ut8 **)&p, end);
break;
case BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
seg_idx = imm;
@ -1688,29 +1646,29 @@ static bool reconstruct_chained_fixup(struct MACH0_(obj_t) *bin) {
R_FREE (opcodes);
return false;
} else {
seg_off = read_uleb128 (&ur, end);
seg_off = read_uleb128 (&p, end);
}
break;
case BIND_OPCODE_ADD_ADDR_ULEB:
seg_off += read_uleb128 (&ur, end);
seg_off += read_uleb128 (&p, end);
break;
case BIND_OPCODE_DO_BIND:
break;
case BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
seg_off += read_uleb128 (&ur, end) + wordsize;
seg_off += read_uleb128 (&p, end) + wordsize;
break;
case BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
seg_off += (ut64)imm * (ut64)wordsize + wordsize;
break;
case BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
count = read_uleb128 (&ur, end);
skip = read_uleb128 (&ur, end);
count = read_uleb128 (&p, end);
skip = read_uleb128 (&p, end);
for (j = 0; j < count; j++) {
seg_off += skip + wordsize;
}
break;
default:
bprintf ("Error: unknown bind opcode 0x%02x in dyld_info\n", *ur.p);
bprintf ("Error: unknown bind opcode 0x%02x in dyld_info\n", *p);
R_FREE (opcodes);
return false;
}
@ -2507,14 +2465,14 @@ static char *get_name(struct MACH0_(obj_t) *mo, ut32 stridx, bool filter) {
}
static int walk_exports(struct MACH0_(obj_t) *bin, RExportsIterator iterator, void * ctx) {
#define ULEB(at) read_uleb128 (&ur, end)
#define ULEB(at) read_uleb128 (&p, end)
r_return_val_if_fail (bin, 0);
if (!bin->dyld_info) {
return 0;
}
size_t count = 0;
ulebr ur = {NULL};
ut8 *p = NULL;
ut8 * trie = NULL;
RList * states = NULL;
ut64 size = bin->dyld_info->export_size;
@ -2547,7 +2505,7 @@ static int walk_exports(struct MACH0_(obj_t) *bin, RExportsIterator iterator, vo
do {
RTrieState * state = r_list_get_top (states);
ur.p = state->node;
p = state->node;
ut64 len = ULEB ();
if (len == UT64_MAX) {
break;
@ -2571,7 +2529,7 @@ static int walk_exports(struct MACH0_(obj_t) *bin, RExportsIterator iterator, vo
}
resolver = res + bin->header_at;
} else if (isReexport) {
ur.p += strlen ((char*) ur.p) + 1;
p += strlen ((char*) p) + 1;
// TODO: handle this
}
if (!isReexport) {
@ -2617,17 +2575,17 @@ static int walk_exports(struct MACH0_(obj_t) *bin, RExportsIterator iterator, vo
continue;
}
if (!state->next_child) {
state->next_child = ur.p;
state->next_child = p;
} else {
ur.p = state->next_child;
p = state->next_child;
}
RTrieState * next = R_NEW0 (RTrieState);
if (!next) {
goto beach;
}
next->label = (char *) ur.p;
ur.p += strlen (next->label) + 1;
if (ur.p >= end) {
next->label = (char *) p;
p += strlen (next->label) + 1;
if (p >= end) {
eprintf ("malformed export trie\n");
R_FREE (next);
goto beach;
@ -2656,7 +2614,7 @@ static int walk_exports(struct MACH0_(obj_t) *bin, RExportsIterator iterator, vo
}
next->i = 0;
state->i++;
state->next_child = ur.p;
state->next_child = p;
r_list_push (states, next);
} while (r_list_length (states));
#undef ULEB
@ -3298,16 +3256,16 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
ut64 addr = bin->segs[0].vmaddr;
ut64 segment_end_addr = addr + bin->segs[0].vmsize;
ulebr ur = {opcodes + opcodes_offset};
ut8 *end = ur.p + partition_size;
ut8 *p = opcodes + opcodes_offset;
ut8 *end = p + partition_size;
bool done = false;
while (!done && ur.p < end) {
ut8 imm = *ur.p & BIND_IMMEDIATE_MASK;
ut8 op = *ur.p & BIND_OPCODE_MASK;
ur.p++;
while (!done && p < end) {
ut8 imm = *p & BIND_IMMEDIATE_MASK;
ut8 op = *p & BIND_OPCODE_MASK;
p++;
switch (op) {
#define ULEB() read_uleb128 (&ur, end)
#define SLEB() read_sleb128 (&ur, end)
#define ULEB() read_uleb128 (&p, end)
#define SLEB() r_sleb128 ((const ut8 **)&p, end)
case BIND_OPCODE_DONE: {
bool in_lazy_binds = pidx == 1;
if (!in_lazy_binds) {
@ -3414,8 +3372,8 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
lib_ord = imm? (st8)(BIND_OPCODE_MASK | imm) : 0;
break;
case BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM: {
sym_name = (char*)ur.p;
while (*ur.p++ && ur.p < end) {
sym_name = (char*)p;
while (*p++ && p < end) {
/* empty loop */
}
if (threaded_binds) {
@ -3541,7 +3499,7 @@ RSkipList *MACH0_(get_relocs)(struct MACH0_(obj_t) *bin) {
#undef ULEB
#undef SLEB
default:
bprintf ("Error: unknown bind opcode 0x%02x in dyld_info\n", *ur.p);
bprintf ("Error: unknown bind opcode 0x%02x in dyld_info\n", *p);
R_FREE (opcodes);
r_pvector_free (threaded_binds);
return relocs;

View File

@ -97,7 +97,7 @@ static const char *getstr(RBinDexObj *dex, int idx) {
return NULL;
}
ut64 len;
int uleblen = r_uleb128 (buf, sizeof (buf), &len) - buf;
int uleblen = r_uleb128 (buf, sizeof (buf), &len, NULL) - buf;
if (!uleblen || uleblen >= dex->size || uleblen >= dex->header.strings_size) {
return NULL;
}
@ -854,7 +854,7 @@ static RList *strings(RBinFile *bf) {
goto out_error;
}
r_buf_read_at (bin->b, bin->strings[i], buf, sizeof (buf));
r_uleb128 (buf, sizeof (buf), &len);
r_uleb128 (buf, sizeof (buf), &len, NULL);
if (len > 5 && len < R_BIN_SIZEOF_STRINGS) {
ptr->string = malloc (len + 1);

View File

@ -5,9 +5,9 @@
// compression used to store an arbitrarily large integer in a small number of
// bytes. LEB128 is used in the DWARF debug file format.
R_API const ut8 *r_uleb128(const ut8 *data, int datalen, ut64 *v);
R_API const ut8 *r_uleb128(const ut8 *data, int datalen, ut64 *v, const char **error);
R_API const ut8 *r_uleb128_decode(const ut8 *data, int *datalen, ut64 *v);
R_API int r_uleb128_len (const ut8 *data, int size);
R_API int r_uleb128_len(const ut8 *data, int size);
R_API ut8 *r_uleb128_encode(const ut64 s, int *len);
R_API const ut8 *r_leb128(const ut8 *data, int datalen, st64 *v);
R_API st64 r_sleb128(const ut8 **data, const ut8 *end);

View File

@ -1,13 +1,15 @@
/* radare - LGPL - Copyright 2014-2015 - pancake */
#include "r_util/r_str.h"
#include <r_util.h>
/* dex/dwarf uleb128 implementation */
R_API const ut8 *r_uleb128(const ut8 *data, int datalen, ut64 *v) {
R_API const ut8 *r_uleb128(const ut8 *data, int datalen, ut64 *v, const char **error) {
ut8 c;
ut64 s, sum = 0;
const ut8 *data_end;
bool malformed_uleb = true;
if (v) {
*v = 0LL;
}
@ -24,14 +26,23 @@ R_API const ut8 *r_uleb128(const ut8 *data, int datalen, ut64 *v) {
for (s = 0; data < data_end; s += 7) {
c = *(data++) & 0xff;
if (s > 63) {
eprintf ("r_uleb128: undefined behaviour in %d shift on ut32\n", (int)s);
if (error) {
*error = r_str_newf ("r_uleb128: undefined behaviour in %d shift on ut32\n", (int)s);
}
break;
} else {
sum |= ((ut64) (c & 0x7f) << s);
}
if (!(c & 0x80)) {
malformed_uleb = false;
break;
}
}
if (malformed_uleb) {
if (error) {
*error = r_str_newf ("malformed uleb128\n");
}
}
} else {
data++;
}

View File

@ -0,0 +1,9 @@
NAME=macho trie malformed uleb128
FILE=bins/mach0/macho-trie-bad-export-info-malformed-uleb128
CMDS=<<EOF
EOF
EXPECT_ERR=<<EOF
malformed uleb128
malformed uleb128
EOF
RUN

View File

@ -10,7 +10,7 @@ bool test_uleb128_small(void) {
mu_assert_memeq (data, (ut8 *)"\xef\xfd\x02", 3, "right bytes");
ut64 val;
r_uleb128 (data, len, &val);
r_uleb128 (data, len, &val, NULL);
mu_assert_eq (val, 0xbeef, "uleb128 decoded");
r_uleb128_decode (data, &len, &val);
@ -47,7 +47,7 @@ bool test_uleb128_big(void) {
mu_assert_memeq (data, (ut8 *)"\xa3\xe0\xd4\xb9\xbf\x86\x02", 7, "right bytes");
ut64 val;
r_uleb128 (data, len, &val);
r_uleb128 (data, len, &val, NULL);
mu_assert_eq (val, 9019283812387, "uleb128 decoded");
r_uleb128_decode (data, &len, &val);