Fix #2455 - several ASAN crashes in the PE parser

This commit is contained in:
pancake 2015-04-30 01:33:52 +02:00
parent 55809a1bd3
commit 79b4820eaf
2 changed files with 57 additions and 12 deletions

View File

@ -411,8 +411,9 @@ static struct r_bin_pe_export_t* parse_symbol_table(struct PE_(r_bin_pe_obj_t)*
} else {
char *longname, name[128];
ut32 *idx = (ut32 *) (buf+I+4) ;
if (r_buf_read_at (bin->b, off+ *idx+shsz, (ut8*)name, 128)) {
if (r_buf_read_at (bin->b, off+ *idx+shsz, (ut8*)name, 128)) {// == 128) {
longname = name;
name[sizeof(name)-1] = 0;
D printf ("0x%08"PFMT64x" %s\n", text + sr->value, longname);
strncpy ((char*)exp[symctr].name, longname, PE_NAME_LENGTH-1);
} else {
@ -542,8 +543,8 @@ static int PE_(r_bin_pe_init_imports)(struct PE_(r_bin_pe_obj_t) *bin) {
bin->import_directory = NULL;
if (import_dir_paddr != 0) {
if (import_dir_size<1 || import_dir_size>maxidsz) {
eprintf ("Warning: Invalid import directory size: 0x%x\n",
import_dir_size);
eprintf ("Warning: Invalid import directory size: 0x%x is now 0x%x\n",
import_dir_size, maxidsz);
import_dir_size = maxidsz;
}
bin->import_directory_offset = import_dir_offset;
@ -1927,13 +1928,28 @@ struct r_bin_pe_import_t* PE_(r_bin_pe_get_imports)(struct PE_(r_bin_pe_obj_t) *
if (!bin)
return NULL;
if (bin->import_directory_offset+32 >= bin->b->length) {
return NULL;
}
if (bin->import_directory_offset < bin->size && bin->import_directory_offset > 0) {
void *last;
curr_import_dir = (PE_(image_import_directory)*)(bin->b->buf + bin->import_directory_offset);
dll_name_offset = curr_import_dir->Name;
void *last = curr_import_dir + bin->import_directory_size;
while (curr_import_dir->FirstThunk != 0 || curr_import_dir->Name != 0 ||
if (bin->import_directory_offset<1) {
return NULL;
}
if (bin->import_directory_size<1) {
return NULL;
}
if (bin->import_directory_offset+bin->import_directory_size > bin->b->length) {
eprintf ("Error: read (import directory too big)\n");
bin->import_directory_size = bin->b->length - bin->import_directory_offset;
}
last = curr_import_dir + bin->import_directory_size;
while (((void*)curr_import_dir+sizeof (*curr_import_dir)) < last && (
curr_import_dir->FirstThunk != 0 || curr_import_dir->Name != 0 ||
curr_import_dir->TimeDateStamp != 0 || curr_import_dir->Characteristics != 0 ||
curr_import_dir->ForwarderChain != 0) {
curr_import_dir->ForwarderChain != 0)) {
dll_name_offset = curr_import_dir->Name;
int rr = r_buf_read_at (bin->b,
PE_(r_bin_pe_vaddr_to_paddr)(bin, dll_name_offset),
@ -1944,10 +1960,11 @@ struct r_bin_pe_import_t* PE_(r_bin_pe_get_imports)(struct PE_(r_bin_pe_obj_t) *
}
if (!PE_(r_bin_pe_parse_imports)(bin, &imports, &nimp, dll_name,
curr_import_dir->Characteristics,
curr_import_dir->FirstThunk))
curr_import_dir->FirstThunk)) {
break;
}
curr_import_dir++;
if ((void*)curr_import_dir>= last) {
if (curr_import_dir+2 >= last) {
break;
}
}
@ -2008,17 +2025,35 @@ struct r_bin_pe_lib_t* PE_(r_bin_pe_get_libs)(struct PE_(r_bin_pe_obj_t) *bin) {
return NULL;
}
if (bin->import_directory_offset + bin->import_directory_size > bin->b->length) {
eprintf ("import directory offset bigger than file\n");
bin->import_directory_size = bin->b->length - bin->import_directory_offset;
return NULL;
}
RStrHT *lib_map = r_strht_new();
if (bin->import_directory_offset < bin->size && bin->import_directory_offset > 0) {
void *last = NULL;
// normal imports
curr_import_dir = (PE_(image_import_directory)*)(
bin->b->buf + bin->import_directory_offset);
while (curr_import_dir->FirstThunk != 0 || curr_import_dir->Name != 0 ||
if (bin->import_directory_offset+bin->import_directory_size > bin->b->length) {
// chop
bin->import_directory_size = bin->b->length - bin->import_directory_offset;
eprintf ("Warning: read libs (import directory too big) %d %d size %d\n",
bin->import_directory_offset, bin->import_directory_size, bin->b->length);
//return NULL;
}
last = curr_import_dir + bin->import_directory_size;
while ((void*)(curr_import_dir+1) < last && (
curr_import_dir->FirstThunk != 0 || curr_import_dir->Name != 0 ||
curr_import_dir->TimeDateStamp != 0 || curr_import_dir->Characteristics != 0 ||
curr_import_dir->ForwarderChain != 0) {
curr_import_dir->ForwarderChain != 0)) {
name_off = PE_(r_bin_pe_vaddr_to_paddr)(bin, curr_import_dir->Name);
len = r_buf_read_at (bin->b, name_off, (ut8*)libs[index].name, PE_STRING_LENGTH);
if (len <2) { // minimum string length
if (libs[index].name[0] == 0) { // minimum string length
break;
}
if (len <2 || libs[index].name[0] == 0) { // minimum string length
eprintf ("Error: read (libs - import dirs) %d\n", len);
break;
}
@ -2038,6 +2073,10 @@ struct r_bin_pe_lib_t* PE_(r_bin_pe_get_libs)(struct PE_(r_bin_pe_obj_t) *bin) {
}
}
curr_import_dir++;
if ((void*)curr_import_dir >= last) {
eprintf ("eof in imports dir\n");
break;
}
}
}

View File

@ -1551,7 +1551,13 @@ static int bin_libs (RCore *r, int mode) {
r_cons_printf ("%s\n", lib);
i++;
}
if (!mode) r_cons_printf ("\n%i libraries\n", i);
if (!mode) {
if (i==1) {
r_cons_printf ("\n%i library\n", i);
} else {
r_cons_printf ("\n%i libraries\n", i);
}
}
}
return R_TRUE;
}