From 3b2c41f85e67889825d4d317af3d2f72260b8dd0 Mon Sep 17 00:00:00 2001 From: pancake Date: Sat, 22 Jun 2024 22:33:36 +0200 Subject: [PATCH 1/3] WIP: Early catch some missbehaves in the class parsing and speedup macho parsing ##bin --- libr/bin/bobj.c | 11 ++++++++++- libr/bin/format/objc/mach0_classes.c | 14 ++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/libr/bin/bobj.c b/libr/bin/bobj.c index 0ff7076fae47b..db476d1f057eb 100644 --- a/libr/bin/bobj.c +++ b/libr/bin/bobj.c @@ -267,7 +267,14 @@ 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) { + if (R_STR_ISEMPTY (fname)) { + R_LOG_WARN ("Corrupted class storage"); + break; +#if 0 + R_LOG_DEBUG ("Invalid class, must be removed"); + continue; +#endif + } else { r_bin_name_update (cls->name, fname); free (fname); } @@ -450,6 +457,7 @@ R_API int r_bin_object_set_items(RBinFile *bf, RBinObject *bo) { filter_classes (bf, bo->classes); } // cache addr=class+method +#if 0 if (bo->classes) { RList *klasses = bo->classes; RListIter *iter, *iter2; @@ -465,6 +473,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..9331bdb348eb2 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"); @@ -1859,6 +1865,10 @@ RList *MACH0_(parse_classes)(RBinFile *bf, objc_cache_opt_info *oi) { free (klass_name); num_of_unnamed_class++; } + if (strlen (klass->name) > 512) { + eprintf ("Invalid class name, probably corrupted binary\n"); + break; + } r_list_append (ret, klass); } metadata_sections_fini (&ms); @@ -2049,6 +2059,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); } From ca201564acc8b6cc21b078c7428d2b7a844f7055 Mon Sep 17 00:00:00 2001 From: pancake Date: Tue, 9 Jul 2024 20:40:11 +0200 Subject: [PATCH 2/3] morefixes --- libr/bin/bobj.c | 15 +++++---------- libr/bin/format/objc/mach0_classes.c | 4 ++-- libr/core/canal.c | 18 ++++++++++++++++++ test/db/formats/mach0/swift | 2 ++ 4 files changed, 27 insertions(+), 12 deletions(-) diff --git a/libr/bin/bobj.c b/libr/bin/bobj.c index db476d1f057eb..e8009c60f9512 100644 --- a/libr/bin/bobj.c +++ b/libr/bin/bobj.c @@ -268,16 +268,11 @@ static void filter_classes(RBinFile *bf, RList *list) { const char *kname = r_bin_name_tostring (cls->name); char *fname = r_bin_filter_name (bf, db, cls->index, kname); if (R_STR_ISEMPTY (fname)) { - R_LOG_WARN ("Corrupted class storage"); + R_LOG_INFO ("Corrupted class storage with nameless classes"); break; -#if 0 - R_LOG_DEBUG ("Invalid class, must be removed"); - continue; -#endif - } else { - r_bin_name_update (cls->name, fname); - free (fname); } + 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); } @@ -332,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")) { @@ -344,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 @@ -458,6 +451,8 @@ R_API int r_bin_object_set_items(RBinFile *bf, RBinObject *bo) { } // 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; diff --git a/libr/bin/format/objc/mach0_classes.c b/libr/bin/format/objc/mach0_classes.c index 9331bdb348eb2..4988657c52b76 100644 --- a/libr/bin/format/objc/mach0_classes.c +++ b/libr/bin/format/objc/mach0_classes.c @@ -835,7 +835,7 @@ 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)); + // eprintf ("%d %d\n", name_len, strlen (name)); if (len < 1) { goto error; } @@ -1866,7 +1866,7 @@ RList *MACH0_(parse_classes)(RBinFile *bf, objc_cache_opt_info *oi) { num_of_unnamed_class++; } if (strlen (klass->name) > 512) { - eprintf ("Invalid class name, probably corrupted binary\n"); + R_LOG_INFO ("Invalid class name, probably corrupted binary"); break; } r_list_append (ret, klass); 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=< Date: Tue, 9 Jul 2024 21:04:24 +0200 Subject: [PATCH 3/3] first iter --- libr/bin/format/objc/mach0_classes.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/libr/bin/format/objc/mach0_classes.c b/libr/bin/format/objc/mach0_classes.c index 4988657c52b76..ee7a8d6a730f9 100644 --- a/libr/bin/format/objc/mach0_classes.c +++ b/libr/bin/format/objc/mach0_classes.c @@ -1859,16 +1859,18 @@ 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); num_of_unnamed_class++; } - if (strlen (klass->name) > 512) { - R_LOG_INFO ("Invalid class name, probably corrupted binary"); - break; - } r_list_append (ret, klass); } metadata_sections_fini (&ms);