diff --git a/libr/bin/bobj.c b/libr/bin/bobj.c index 0ff7076fae47b..e8009c60f9512 100644 --- a/libr/bin/bobj.c +++ b/libr/bin/bobj.c @@ -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); } @@ -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")) { @@ -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 @@ -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; @@ -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); diff --git a/libr/bin/format/objc/mach0_classes.c b/libr/bin/format/objc/mach0_classes.c index c79fd77ad0988..ee7a8d6a730f9 100644 --- a/libr/bin/format/objc/mach0_classes.c +++ b/libr/bin/format/objc/mach0_classes.c @@ -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); @@ -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"); @@ -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); @@ -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); } diff --git a/libr/core/canal.c b/libr/core/canal.c index ed2627673edda..6c9cdab019f24 100644 --- a/libr/core/canal.c +++ b/libr/core/canal.c @@ -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); diff --git a/test/db/formats/mach0/swift b/test/db/formats/mach0/swift index b1561d0fa026f..c54221457a0dc 100644 --- a/test/db/formats/mach0/swift +++ b/test/db/formats/mach0/swift @@ -2044,6 +2044,7 @@ EXPECT=<