Fix #1702 - Revert and fix the dwarf/dex crashes related to uleb overflows
This commit is contained in:
parent
12f598d77d
commit
3a31198ffd
|
@ -193,6 +193,7 @@ static const ut8 *r_bin_dwarf_parse_lnp_header (
|
|||
RBinDwarfLNPHeader *hdr, FILE *f)
|
||||
{
|
||||
int i;
|
||||
Sdb *s;
|
||||
size_t count;
|
||||
const ut8 *tmp_buf = NULL;
|
||||
|
||||
|
@ -203,7 +204,7 @@ static const ut8 *r_bin_dwarf_parse_lnp_header (
|
|||
hdr->unit_length.part2 = READ (buf, ut32);
|
||||
}
|
||||
|
||||
Sdb *s = sdb_new (NULL, NULL, 0);
|
||||
s = sdb_new (NULL, NULL, 0);
|
||||
|
||||
hdr->version = READ (buf, ut16);
|
||||
|
||||
|
@ -270,9 +271,9 @@ static const ut8 *r_bin_dwarf_parse_lnp_header (
|
|||
break;
|
||||
}
|
||||
buf += len + 1;
|
||||
buf = r_uleb128 (buf, &id_idx);
|
||||
buf = r_uleb128 (buf, &mod_time);
|
||||
buf = r_uleb128 (buf, &file_len);
|
||||
buf = r_uleb128 (buf, buf_end-buf, &id_idx);
|
||||
buf = r_uleb128 (buf, buf_end-buf, &mod_time);
|
||||
buf = r_uleb128 (buf, buf_end-buf, &file_len);
|
||||
|
||||
|
||||
if (i) {
|
||||
|
@ -419,10 +420,10 @@ static const ut8* r_bin_dwarf_parse_ext_opcode(const RBin *a, const ut8 *obuf,
|
|||
|
||||
buf += (strlen (filename) + 1);
|
||||
ut64 dir_idx;
|
||||
buf = r_uleb128 (buf, &dir_idx);
|
||||
buf = r_uleb128 (buf, -1, &dir_idx);
|
||||
break;
|
||||
case DW_LNE_set_discriminator:
|
||||
buf = r_uleb128(buf, &addr);
|
||||
buf = r_uleb128(buf, -1, &addr);
|
||||
if (f) {
|
||||
fprintf(f, "set Discriminator to %lld\n", addr);
|
||||
}
|
||||
|
@ -513,7 +514,7 @@ static const ut8* r_bin_dwarf_parse_std_opcode(
|
|||
regs->basic_block = DWARF_FALSE;
|
||||
break;
|
||||
case DW_LNS_advance_pc:
|
||||
buf = r_uleb128 (buf, &addr);
|
||||
buf = r_uleb128 (buf, -1, &addr);
|
||||
regs->address += addr * hdr->min_inst_len;
|
||||
|
||||
if (f) {
|
||||
|
@ -529,14 +530,14 @@ static const ut8* r_bin_dwarf_parse_std_opcode(
|
|||
}
|
||||
break;
|
||||
case DW_LNS_set_file:
|
||||
buf = r_uleb128 (buf, &addr);
|
||||
buf = r_uleb128 (buf, -1, &addr);
|
||||
if (f) {
|
||||
fprintf(f, "Set file to %lld\n", addr);
|
||||
}
|
||||
regs->file = addr;
|
||||
break;
|
||||
case DW_LNS_set_column:
|
||||
buf = r_uleb128(buf, &addr);
|
||||
buf = r_uleb128(buf, -1, &addr);
|
||||
if (f) {
|
||||
fprintf(f, "Set column to %lld\n", addr);
|
||||
}
|
||||
|
@ -583,7 +584,7 @@ static const ut8* r_bin_dwarf_parse_std_opcode(
|
|||
}
|
||||
break;
|
||||
case DW_LNS_set_isa:
|
||||
buf = r_uleb128(buf, &addr);
|
||||
buf = r_uleb128(buf, -1, &addr);
|
||||
regs->isa = addr;
|
||||
if (f) {
|
||||
fprintf(f, "set_isa\n");
|
||||
|
@ -1160,7 +1161,7 @@ static const ut8 *r_bin_dwarf_parse_attr_value (const ut8 *obuf,
|
|||
break;
|
||||
|
||||
case DW_FORM_block:
|
||||
buf = r_uleb128 (buf, &value->encoding.block.length);
|
||||
buf = r_uleb128 (buf, -1, &value->encoding.block.length);
|
||||
|
||||
value->encoding.block.data = calloc(sizeof(ut8),
|
||||
value->encoding.block.length);
|
||||
|
@ -1202,7 +1203,7 @@ static const ut8 *r_bin_dwarf_parse_attr_value (const ut8 *obuf,
|
|||
break;
|
||||
|
||||
case DW_FORM_udata:
|
||||
buf = r_uleb128 (buf, &value->encoding.data);
|
||||
buf = r_uleb128 (buf, -1, &value->encoding.data);
|
||||
break;
|
||||
|
||||
case DW_FORM_ref_addr:
|
||||
|
@ -1248,7 +1249,7 @@ static const ut8 *r_bin_dwarf_parse_comp_unit(Sdb *s, const ut8 *obuf,
|
|||
if (cu->length && cu->capacity == cu->length)
|
||||
r_bin_dwarf_expand_cu (cu);
|
||||
|
||||
buf = r_uleb128 (buf, &abbr_code);
|
||||
buf = r_uleb128 (buf, -1, &abbr_code);
|
||||
|
||||
if (abbr_code > da->length) {
|
||||
return NULL;
|
||||
|
@ -1369,7 +1370,7 @@ static RBinDwarfDebugAbbrev *r_bin_dwarf_parse_abbrev_raw(const ut8 *obuf, size_
|
|||
|
||||
while (buf < buf_end) {
|
||||
offset = buf - obuf;
|
||||
buf = r_uleb128(buf, &tmp);
|
||||
buf = r_uleb128 (buf, -1, &tmp);
|
||||
if (!tmp)
|
||||
continue;
|
||||
|
||||
|
@ -1381,7 +1382,7 @@ static RBinDwarfDebugAbbrev *r_bin_dwarf_parse_abbrev_raw(const ut8 *obuf, size_
|
|||
r_bin_dwarf_init_abbrev_decl(tmpdecl);
|
||||
|
||||
tmpdecl->code = tmp;
|
||||
buf = r_uleb128(buf, &tmp);
|
||||
buf = r_uleb128 (buf, -1, &tmp);
|
||||
tmpdecl->tag = tmp;
|
||||
|
||||
tmpdecl->offset = offset;
|
||||
|
@ -1391,8 +1392,8 @@ static RBinDwarfDebugAbbrev *r_bin_dwarf_parse_abbrev_raw(const ut8 *obuf, size_
|
|||
if (tmpdecl->length == tmpdecl->capacity)
|
||||
r_bin_dwarf_expand_abbrev_decl(tmpdecl);
|
||||
|
||||
buf = r_uleb128(buf, &spec1);
|
||||
buf = r_uleb128(buf, &spec2);
|
||||
buf = r_uleb128(buf, -1, &spec1);
|
||||
buf = r_uleb128(buf, -1, &spec2);
|
||||
|
||||
tmpdecl->specs[tmpdecl->length].attr_name = spec1;
|
||||
tmpdecl->specs[tmpdecl->length].attr_form = spec2;
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
#include <r_types.h>
|
||||
#include <r_types.h>
|
||||
#include <r_util.h>
|
||||
#include <r_lib.h>
|
||||
#include <r_bin.h>
|
||||
|
|
|
@ -51,7 +51,10 @@ static ut64 baddr(RBinFile *arch) {
|
|||
}
|
||||
|
||||
static char *flagname (const char *class, const char *method) {
|
||||
char *p, *str, *s = malloc (strlen (class) + strlen (method)+2);
|
||||
char *p, *str, *s;
|
||||
if (!class || !method)
|
||||
return NULL;
|
||||
s = malloc (strlen (class) + strlen (method)+2);
|
||||
str = s;
|
||||
p = (char*)r_str_lchr (class, '$');
|
||||
if (!p) p = (char *)r_str_lchr (class, '/');
|
||||
|
@ -235,9 +238,13 @@ static char *get_string (struct r_bin_dex_obj_t *bin, int idx) {
|
|||
const ut8 buf[128], *buf2;
|
||||
ut64 len;
|
||||
int uleblen;
|
||||
if (idx<0)
|
||||
return NULL;
|
||||
if (idx>=bin->header.strings_size)
|
||||
return NULL;
|
||||
r_buf_read_at (bin->b, bin->strings[idx], (ut8*)&buf, 8);
|
||||
len = dex_read_uleb128 (buf);
|
||||
buf2 = r_uleb128 (buf, &len);
|
||||
buf2 = r_uleb128 (buf, -1, &len);
|
||||
uleblen = (size_t)(buf2 - buf);
|
||||
// XXX what about 0 length strings?
|
||||
if (len>0 && len < R_BIN_SIZEOF_STRINGS) {
|
||||
|
@ -254,10 +261,10 @@ static char *get_string (struct r_bin_dex_obj_t *bin, int idx) {
|
|||
/* TODO: check boundaries */
|
||||
static char *dex_method_name (RBinDexObj *bin, int idx) {
|
||||
int tid;
|
||||
if (idx<0 || idx>bin->header.method_size)
|
||||
if (idx<0 || idx>=bin->header.method_size)
|
||||
return NULL;
|
||||
tid = bin->methods[idx].name_id;
|
||||
if (tid<0 || tid>bin->header.strings_size)
|
||||
if (tid<0 || tid>=bin->header.strings_size)
|
||||
return NULL;
|
||||
return get_string (bin, tid);
|
||||
}
|
||||
|
@ -267,6 +274,8 @@ static char *dex_class_name (RBinDexObj *bin, RBinDexClass *c) {
|
|||
if (!bin || !c || !bin->types)
|
||||
return NULL;
|
||||
cid = c->super_class;
|
||||
if (cid<0 || cid >= bin->header.types_size)
|
||||
return NULL;
|
||||
tid = bin->types [cid].descriptor_id;
|
||||
//int sid = bin->strings[tid];
|
||||
return get_string (bin, tid);
|
||||
|
@ -277,6 +286,8 @@ static char *dex_class_super_name (RBinDexObj *bin, RBinDexClass *c) {
|
|||
if (!bin || !c || !bin->types)
|
||||
return NULL;
|
||||
cid = c->super_class;
|
||||
if (cid<0 || cid >= bin->header.types_size)
|
||||
return NULL;
|
||||
tid = bin->types [cid].descriptor_id;
|
||||
//int sid = bin->strings[tid];
|
||||
return get_string (bin, tid);
|
||||
|
@ -286,7 +297,7 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
int *methods;
|
||||
int i, j;
|
||||
char *name;
|
||||
const ut8 *p;
|
||||
const ut8 *p, *p_end;
|
||||
|
||||
// doublecheck??
|
||||
if (bin->methods_list)
|
||||
|
@ -317,6 +328,11 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
return R_FALSE;
|
||||
}
|
||||
|
||||
if (bin->header.strings_size > bin->size) {
|
||||
eprintf ("Invalid strings size\n");
|
||||
return R_FALSE;
|
||||
}
|
||||
|
||||
dprintf ("Walking %d classes\n", bin->header.class_size);
|
||||
if (bin->classes)
|
||||
for (i=0; i<bin->header.class_size; i++) {
|
||||
|
@ -333,19 +349,20 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
// sdb_queryf ("class.%s.super=%s", super_name)
|
||||
// sdb_queryf ("class.%s.methods=%d", class_name, DM);
|
||||
p = r_buf_get_at (arch->buf, c->class_data_offset, NULL);
|
||||
p_end = p + (arch->buf->length - c->class_data_offset);
|
||||
/* data header */
|
||||
{
|
||||
ut64 SF, IF, DM, VM;
|
||||
p = r_uleb128 (p, &SF);
|
||||
p = r_uleb128 (p, &IF);
|
||||
p = r_uleb128 (p, &DM);
|
||||
p = r_uleb128 (p, &VM);
|
||||
p = r_uleb128 (p, p_end-p, &SF);
|
||||
p = r_uleb128 (p, p_end-p, &IF);
|
||||
p = r_uleb128 (p, p_end-p, &DM);
|
||||
p = r_uleb128 (p, p_end-p, &VM);
|
||||
dprintf (" static fields: %u\n", (ut32)SF);
|
||||
/* static fields */
|
||||
for (j=0; j<SF; j++) {
|
||||
ut64 FI, FA;
|
||||
p = r_uleb128 (p, &FI);
|
||||
p = r_uleb128 (p, &FA);
|
||||
p = r_uleb128 (p, p_end-p, &FI);
|
||||
p = r_uleb128 (p, p_end-p, &FA);
|
||||
dprintf (" field_idx: %u\n", (ut32)FI);
|
||||
dprintf (" field access_flags: %u\n", (ut32)FA);
|
||||
}
|
||||
|
@ -353,8 +370,8 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
dprintf (" instance fields: %u\n", (ut32)IF);
|
||||
for (j=0; j<IF; j++) {
|
||||
ut64 FI, FA;
|
||||
p = r_uleb128 (p, &FI);
|
||||
p = r_uleb128 (p, &FA);
|
||||
p = r_uleb128 (p, -1, &FI);
|
||||
p = r_uleb128 (p, -1, &FA);
|
||||
dprintf (" field_idx: %u,\n", (ut32)FI);
|
||||
dprintf (" field access_flags: %u,\n", (ut32)FA);
|
||||
}
|
||||
|
@ -363,9 +380,9 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
for (j=0; j<DM; j++) {
|
||||
char *method_name, *flag_name;
|
||||
ut64 MI, MA, MC;
|
||||
p = r_uleb128 (p, &MI);
|
||||
p = r_uleb128 (p, &MA);
|
||||
p = r_uleb128 (p, &MC);
|
||||
p = r_uleb128 (p, -1, &MI);
|
||||
p = r_uleb128 (p, -1, &MA);
|
||||
p = r_uleb128 (p, -1, &MC);
|
||||
|
||||
if (MI<bin->header.method_size) methods[MI] = 1;
|
||||
if (MC>0 && bin->code_from>MC) bin->code_from = MC;
|
||||
|
@ -381,7 +398,7 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
dprintf (" access_flags: 0x%x,\n", (ut32)MA);
|
||||
dprintf (" code_offset: 0x%x },\n", (ut32)MC);
|
||||
/* add symbol */
|
||||
{
|
||||
if (flag_name && *flag_name) {
|
||||
RBinSymbol *sym = R_NEW0 (RBinSymbol);
|
||||
strncpy (sym->name, flag_name, R_BIN_SIZEOF_STRINGS);
|
||||
strcpy (sym->type, "FUNC");
|
||||
|
@ -395,9 +412,9 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
dprintf (" virtual methods: %u\n", (ut32)VM);
|
||||
for (j=0; j<VM; j++) {
|
||||
ut64 MI, MA, MC;
|
||||
p = r_uleb128 (p, &MI);
|
||||
p = r_uleb128 (p, &MA);
|
||||
p = r_uleb128 (p, &MC);
|
||||
p = r_uleb128 (p, -1, &MI);
|
||||
p = r_uleb128 (p, -1, &MA);
|
||||
p = r_uleb128 (p, -1, &MC);
|
||||
|
||||
if (MI<bin->header.method_size) methods[MI] = 1;
|
||||
if (bin->code_from>MC) bin->code_from = MC;
|
||||
|
@ -422,7 +439,7 @@ static int dex_loadcode(RBinFile *arch, RBinDexObj *bin) {
|
|||
if (!methods[i]) {
|
||||
char *method_name = dex_method_name (bin, i);
|
||||
dprintf ("import %d (%s)\n", i, method_name);
|
||||
{
|
||||
if (method_name && *method_name) {
|
||||
RBinSymbol *sym = R_NEW0 (RBinSymbol);
|
||||
strncpy (sym->name, method_name, R_BIN_SIZEOF_STRINGS);
|
||||
strcpy (sym->type, "FUNC");
|
||||
|
|
|
@ -593,7 +593,7 @@ R_API void r_big_mod(RNumBig *c, RNumBig *a, RNumBig *b);
|
|||
#endif
|
||||
|
||||
/* uleb */
|
||||
R_API const ut8 *r_uleb128 (const ut8 *data, ut64 *v);
|
||||
R_API const ut8 *r_uleb128 (const ut8 *data, int datalen, ut64 *v);
|
||||
R_API const ut8 *r_leb128 (const ut8 *data, st64 *v);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -2,12 +2,18 @@
|
|||
|
||||
/* dex/dwarf uleb128 implementation */
|
||||
|
||||
R_API const ut8 *r_uleb128 (const ut8 *data, ut64 *v) {
|
||||
R_API const ut8 *r_uleb128 (const ut8 *data, int datalen, ut64 *v) {
|
||||
ut8 c;
|
||||
ut64 s, sum = 0;
|
||||
if (data) {
|
||||
const ut8 *data_end;
|
||||
if (datalen==-1) {
|
||||
// WARNING; possible overflow
|
||||
datalen = 0xffff;
|
||||
}
|
||||
data_end = data + datalen;
|
||||
if (data && datalen>0) {
|
||||
if (*data) {
|
||||
for (s = 0; ; s += 7) {
|
||||
for (s = 0; data<data_end; s += 7) {
|
||||
c = *(data++) & 0xff;
|
||||
sum |= ((ut32) (c&0x7f) << s);
|
||||
if (!(c&0x80)) break;
|
||||
|
|
Loading…
Reference in New Issue