Skip to content

Commit

Permalink
Early catch some missbehaves in the macho class parsing ##bin
Browse files Browse the repository at this point in the history
  • Loading branch information
trufae authored Jul 9, 2024
1 parent 81674a5 commit 5a2a903
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 6 deletions.
14 changes: 9 additions & 5 deletions libr/bin/bobj.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,10 +267,12 @@ static void filter_classes(RBinFile *bf, RList *list) {
r_list_foreach (list, iter, cls) {
const char *kname = r_bin_name_tostring (cls->name);
char *fname = r_bin_filter_name (bf, db, cls->index, kname);
if (fname) {
r_bin_name_update (cls->name, fname);
free (fname);
if (R_STR_ISEMPTY (fname)) {
R_LOG_INFO ("Corrupted class storage with nameless classes");
break;
}
r_bin_name_update (cls->name, fname);
free (fname);
r_list_foreach (cls->methods, iter2, sym) {
r_bin_filter_sym (bf, ht, sym->vaddr, sym);
}
Expand Down Expand Up @@ -325,7 +327,6 @@ R_API int r_bin_object_set_items(RBinFile *bf, RBinObject *bo) {
int minlen = (bf->rbin->minstrlen > 0) ? bf->rbin->minstrlen : p->minstrlen;
bf->bo = bo;

#if 0
bo->info = p->info? p->info (bf): NULL;
if (bo->info && bo->info->type) {
if (strstr (bo->info->type, "CORE")) {
Expand All @@ -337,7 +338,6 @@ R_API int r_bin_object_set_items(RBinFile *bf, RBinObject *bo) {
}
}
}
#endif
// XXX: no way to get info from xtr pluginz?
// Note, object size can not be set from here due to potential
// inconsistencies
Expand Down Expand Up @@ -450,6 +450,9 @@ R_API int r_bin_object_set_items(RBinFile *bf, RBinObject *bo) {
filter_classes (bf, bo->classes);
}
// cache addr=class+method
#if 0
// moved into libr/core/canal.c
// XXX SLOW on large binaries. only used when needed by getFunctionName from canal.c
if (bo->classes) {
RList *klasses = bo->classes;
RListIter *iter, *iter2;
Expand All @@ -465,6 +468,7 @@ R_API int r_bin_object_set_items(RBinFile *bf, RBinObject *bo) {
}
}
}
#endif
}
if (p->lines) {
bo->lines = p->lines (bf);
Expand Down
18 changes: 17 additions & 1 deletion libr/bin/format/objc/mach0_classes.c
Original file line number Diff line number Diff line change
Expand Up @@ -835,12 +835,16 @@ static void get_method_list(RBinFile *bf, RBinClass *klass, const char *class_na
name = malloc (name_len + 1);
len = r_buf_read_at (bf->buf, r, (ut8 *)name, name_len);
name[name_len] = 0;
// eprintf ("%d %d\n", name_len, strlen (name));
if (len < 1) {
goto error;
}
}
if (class_name) { // XXX to save memory we can just ref the RBinName instance from the class
method->classname = strdup (class_name);
} else {
R_LOG_ERROR ("Invalid class name for method. Avoid parsing invalid data");
goto error;
}
method->name = r_bin_name_new (name);
R_FREE (name);
Expand Down Expand Up @@ -1293,6 +1297,8 @@ static void get_class_ro_t(RBinFile *bf, bool *is_meta_class, RBinClass *klass,
return;
}
if (bin->has_crypto) {
R_LOG_ERROR ("Not parsing encrypted data");
return;
const char kn[] = "some_encrypted_data";
klass->name = r_bin_name_new (kn);
// klass->name = strdup ("some_encrypted_data");
Expand Down Expand Up @@ -1853,7 +1859,13 @@ RList *MACH0_(parse_classes)(RBinFile *bf, objc_cache_opt_info *oi) {
}
p = r_read_ble (&pp[0], bigendian, 8 * sizeof (mach0_ut));
MACH0_(get_class_t) (bf, klass, p, false, relocs, oi);
if (!klass->name) {
if (klass->name) {
const char *klass_name = r_bin_name_tostring (klass->name);
if (strlen (klass_name) > 512) {
R_LOG_INFO ("Invalid class name, probably corrupted binary");
break;
}
} else {
char *klass_name = r_str_newf ("UnnamedClass%" PFMT64d, num_of_unnamed_class);
klass->name = r_bin_name_new (klass_name);
free (klass_name);
Expand Down Expand Up @@ -2049,6 +2061,10 @@ void MACH0_(get_category_t)(RBinFile *bf, RBinClass *klass, mach0_ut p, const RS
R_FREE (category_name);

const char *klass_name = r_bin_name_tostring (klass->name);
if (R_STR_ISEMPTY (klass_name)) {
R_LOG_ERROR ("Invalid class name");
return;
}
if (c.instanceMethods > 0) {
get_method_list (bf, klass, klass_name, false, oi, c.instanceMethods);
}
Expand Down
18 changes: 18 additions & 0 deletions libr/core/canal.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,27 @@ static int cmpaddr(const void *_a, const void *_b) {
return (a->addr > b->addr)? 1: (a->addr < b->addr)? -1: 0;
}

static void init_addr2klass(RCore *core, RBinObject *bo) {
if (bo->addr2klassmethod) {
return;
}
RList *klasses = bo->classes;
RListIter *iter, *iter2;
RBinClass *klass;
RBinSymbol *method;
// this is slow. must be optimized, but at least its cached
bo->addr2klassmethod = ht_up_new0 ();
r_list_foreach (klasses, iter, klass) {
r_list_foreach (klass->methods, iter2, method) {
ht_up_insert (bo->addr2klassmethod, method->vaddr, method);
}
}
}

static char *get_function_name(RCore *core, ut64 addr) {
RBinFile *bf = r_bin_cur (core->bin);
if (bf && bf->bo) {
init_addr2klass (core, bf->bo);
RBinSymbol *sym = ht_up_find (bf->bo->addr2klassmethod, addr, NULL);
if (sym && sym->classname && sym->name) {
const char *sym_name = r_bin_name_tostring (sym->name);
Expand Down
2 changes: 2 additions & 0 deletions test/db/formats/mach0/swift
Original file line number Diff line number Diff line change
Expand Up @@ -2044,6 +2044,7 @@ EXPECT=<<EOF
},
{
"classname": "WheresMyBrowser.LoadContentViewController",
"rawclassname": "_TtC15WheresMyBrowser25LoadContentViewController",
"addr": 4295178328,
"lang": "objc",
"index": 0,
Expand Down Expand Up @@ -2161,6 +2162,7 @@ EXPECT=<<EOF
},
{
"classname": "WheresMyBrowser.UIWebViewController",
"rawclassname": "_TtC15WheresMyBrowser19UIWebViewController",
"addr": 4295178472,
"lang": "objc",
"index": 0,
Expand Down

0 comments on commit 5a2a903

Please sign in to comment.