Fix #1702 - Revert and fix the dwarf/dex crashes related to uleb overflows

This commit is contained in:
pancake 2014-12-01 23:44:20 +01:00
parent 12f598d77d
commit 3a31198ffd
5 changed files with 66 additions and 43 deletions

View File

@ -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;

View File

@ -1,5 +1,4 @@
#include <r_types.h>
#include <r_types.h>
#include <r_util.h>
#include <r_lib.h>
#include <r_bin.h>

View File

@ -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");

View File

@ -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

View File

@ -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;