Fix #14540 - klass->super must be an RList instead of char* ##bin

This commit is contained in:
pancake 2022-11-21 19:26:29 +01:00 committed by GitHub
parent ddda012afc
commit f09557c7f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 137 additions and 62 deletions

View File

@ -1051,7 +1051,10 @@ R_IPI RBinClass *r_bin_class_new(const char *name, const char *super, int view)
RBinClass *c = R_NEW0 (RBinClass);
if (c) {
c->name = strdup (name);
c->super = super? strdup (super): NULL;
if (super) {
c->super = r_list_newf (free);
r_list_append (c->super, strdup (super));
}
c->methods = r_list_newf (r_bin_symbol_free);
c->fields = r_list_newf (r_bin_field_free);
c->visibility = view;
@ -1062,7 +1065,7 @@ R_IPI RBinClass *r_bin_class_new(const char *name, const char *super, int view)
R_IPI void r_bin_class_free(RBinClass *k) {
if (k) {
free (k->name);
free (k->super);
r_list_free (k->super);
free (k->visibility_str);
r_list_free (k->methods);
r_list_free (k->fields);
@ -1075,8 +1078,9 @@ R_API RBinClass *r_bin_file_add_class(RBinFile *bf, const char *name, const char
RBinClass *c = __getClass (bf, name);
if (c) {
if (super) {
free (c->super);
c->super = strdup (super);
r_list_free (c->super);
c->super = r_list_newf (free);
r_list_append (c->super, strdup (super));
}
return c;
}

View File

@ -1189,7 +1189,8 @@ void MACH0_(get_class_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, bool dupe,
klass->addr = c.isa;
if (c.superclass) {
klass->super = get_class_name (c.superclass, bf);
klass->super = r_list_newf (free);
r_list_append (klass->super, get_class_name (c.superclass, bf));
} else if (relocs) {
struct reloc_t reloc_at_class_addr;
reloc_at_class_addr.addr = p + sizeof (mach0_ut);
@ -1200,7 +1201,8 @@ void MACH0_(get_class_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, bool dupe,
char *target_class_name = (char*) ((struct reloc_t*) found->data)->name;
if (r_str_startswith (target_class_name, _objc_class)) {
target_class_name += _objc_class_len;
klass->super = strdup (target_class_name);
klass->super = r_list_newf (free);
r_list_append (klass->super, strdup (target_class_name));
}
}
}
@ -1208,7 +1210,7 @@ void MACH0_(get_class_t)(mach0_ut p, RBinFile *bf, RBinClass *klass, bool dupe,
#if SWIFT_SUPPORT
if (q (c.data + n_value) & 7) {
eprintf ("This is a Swift class\n");
R_LOG_DEBUG ("This is a Swift class");
}
#endif
if (!is_meta_class && !dupe) {
@ -1616,9 +1618,10 @@ static RList *MACH0_(parse_categories)(RBinFile *bf, RSkipList *relocs, objc_cac
if (cpar) {
*cpar = 0;
}
r_list_free (klass->super);
klass->super = r_list_newf (free);
r_list_append (klass->super, super);
// char *name = strdup (super + idx);
free (klass->super);
klass->super = super;
// free (klass->name);
// klass->name = name;
}

View File

@ -1467,7 +1467,10 @@ static void parse_class(RBinFile *bf, RBinDexClass *c, int class_index, int *met
cls->addr = dex->header.class_offset + (class_index * DEX_CLASS_SIZE);
cls->methods = r_list_new ();
const char *super = dex_class_super_name (dex, c);
cls->super = super? strdup (super): NULL;
if (super) {
cls->super = r_list_newf (free);
r_list_append (cls->super, strdup (super));
}
if (!cls->methods) {
free (cls);
goto beach;
@ -1484,7 +1487,15 @@ static void parse_class(RBinFile *bf, RBinDexClass *c, int class_index, int *met
rbin->cb_printf (" Class descriptor : '%s;'\n", cls->name);
rbin->cb_printf (" Access flags : 0x%04x (%s)\n", c->access_flags,
r_str_get (cls->visibility_str));
rbin->cb_printf (" Superclass : '%s'\n", cls->super);
if (cls->super) {
char *sk;
RListIter *iter;
rbin->cb_printf (" Superclass : '");
r_list_foreach (cls->super, iter, sk) {
rbin->cb_printf ("%s%s", iter->n? ",": "", sk);
}
rbin->cb_printf ("'\n");
}
rbin->cb_printf (" Interfaces -\n");
}

View File

@ -3454,7 +3454,28 @@ static void classdump_c(RCore *r, RBinClass *c) {
static void classdump_objc(RCore *r, RBinClass *c) {
if (c->super) {
r_cons_printf ("@interface %s : %s\n{\n", c->name, c->super);
int n = 0;
r_cons_printf ("@interface %s :", c->name);
const char *sk;
RListIter *iter;
r_list_foreach (c->super, iter, sk) {
switch (n) {
case 0:
r_cons_printf (" %s", sk);
break;
case 1:
r_cons_printf ("< %s", sk);
break;
default:
r_cons_printf (", %s", sk);
break;
}
}
if (r_list_length (c->super) > 1) {
r_cons_printf (" >\n{\n");
} else {
r_cons_printf ("\n{\n");
}
} else {
r_cons_printf ("@interface %s\n{\n", c->name);
}
@ -3586,9 +3607,11 @@ static int bin_classes(RCore *r, PJ *pj, int mode) {
} else if (IS_MODE_SIMPLEST (mode)) {
r_cons_printf ("%s\n", c->name);
} else if (IS_MODE_SIMPLE (mode)) {
char *supers = r_str_list_join (c->super, ", ");
r_cons_printf ("0x%08"PFMT64x" [0x%08"PFMT64x" - 0x%08"PFMT64x"] %s %s%s%s\n",
c->addr, at_min, at_max, r_bin_lang_tostring (c->lang), c->name, c->super ? " " : "",
r_str_get (c->super));
r_str_get (supers));
free (supers);
} else if (IS_MODE_CLASSDUMP (mode)) {
if (c) {
RBinFile *bf = r_bin_cur (r->bin);
@ -3607,14 +3630,17 @@ static int bin_classes(RCore *r, PJ *pj, int mode) {
} else if (IS_MODE_RAD (mode)) {
char *n = __filterShell (name);
r_cons_printf ("\"f class.%s = 0x%"PFMT64x"\"\n", n, at_min);
free (n);
if (c->super) {
char *cn = c->name; // __filterShell (c->name);
char *su = c->super; // __filterShell (c->super);
r_cons_printf ("\"f super.%s.%s = %d\"\n",
cn, su, c->index);
// free (cn);
// free (su);
char *cn = c->name;
RListIter *iter;
const char *sk;
r_list_foreach (c->super, iter, sk) {
char *fsk = strdup (sk);
r_name_filter (fsk, -1);
r_cons_printf ("\"f super.%s.%s = %d\"\n",
cn, fsk, c->index);
free (fsk);
}
}
r_list_foreach (c->methods, iter2, sym) {
char *mflags = r_core_bin_method_flags_str (sym->method_flags, mode);
@ -3662,6 +3688,7 @@ static int bin_classes(RCore *r, PJ *pj, int mode) {
}
}
r_cons_printf ("};\"\n");
free (n);
} else if (IS_MODE_JSON (mode)) {
pj_o (pj);
pj_ks (pj, "classname", c->name);
@ -3673,7 +3700,13 @@ static int bin_classes(RCore *r, PJ *pj, int mode) {
pj_ki (pj, "index", c->index);
if (c->super) {
pj_ks (pj, "visibility", r_str_get (c->visibility_str));
pj_ks (pj, "super", c->super);
RListIter *iter;
const char *sk;
pj_ka (pj, "super");
r_list_foreach (c->super, iter, sk) {
pj_s (pj, sk);
}
pj_end (pj);
}
pj_ka (pj, "methods");
r_list_foreach (c->methods, iter2, sym) {
@ -3723,7 +3756,9 @@ static int bin_classes(RCore *r, PJ *pj, int mode) {
r_cons_printf ("0x%08"PFMT64x" [0x%08"PFMT64x" - 0x%08"PFMT64x"] %6"PFMT64d" %s class %d %s",
c->addr, at_min, at_max, (at_max - at_min), cl, c->index, c->name);
if (c->super) {
r_cons_printf (" :: %s\n", c->super);
char *csv = r_str_list_join (c->super, ", ");
r_cons_printf (" :: %s\n", csv);
free (csv);
} else {
r_cons_newline ();
}

View File

@ -1300,41 +1300,51 @@ static int cmd_info(void *data, const char *input) {
} else if (input[1] == ',') { // "ic,"
// ic,
cmd_ic_comma (core, input);
} else if (input[1] == 'g') {
} else if (input[1] == 'g') { // "icg"
RBinClass *cls;
RListIter *iter;
RListIter *iter, *iter2;
RBinObject *obj = r_bin_cur_object (core->bin);
if (!obj) {
break;
}
bool fullGraph = true;
const char *match = r_str_trim_head_ro (input + 2);
if (*match) {
if (R_STR_ISNOTEMPTY (match)) {
r_list_foreach (obj->classes, iter, cls) {
if (cls->super && strstr (cls->super, match)) {
r_cons_printf ("agn %s\n", cls->super);
r_cons_printf ("agn %s\n", cls->name);
r_cons_printf ("age %s %s\n", cls->super, cls->name);
} else if (strstr (cls->name, match)) {
r_cons_printf ("agn %s\n", cls->name);
char *sk;
if (!match || !strstr (cls->name, match)) {
continue;
}
r_cons_printf ("agn %s\n", cls->name);
if (cls->super) {
r_list_foreach (cls->super, iter2, sk) {
if (match && strstr (sk, match)) {
r_cons_printf ("agn %s\n", sk);
r_cons_printf ("age %s %s\n", sk, cls->name);
}
}
}
}
} else if (fullGraph) {
r_list_foreach (obj->classes, iter, cls) {
if (cls->super) {
r_cons_printf ("agn %s\n", cls->super);
r_cons_printf ("agn %s\n", cls->name);
r_cons_printf ("age %s %s\n", cls->super, cls->name);
} else {
r_cons_printf ("agn %s\n", cls->name);
const char *sk;
r_cons_printf ("agn %s\n", cls->name);
r_list_foreach (cls->super, iter2, sk) {
r_cons_printf ("agn %s\n", sk);
r_cons_printf ("age %s %s\n", sk, cls->name);
}
}
} else {
r_list_foreach (obj->classes, iter, cls) {
if (cls->super && !strstr (cls->super, "NSObject")) {
r_cons_printf ("agn %s\n", cls->super);
char *sk;
RListIter *iter;
r_list_foreach (cls->super, iter, sk) {
if (strstr (sk, "NSObject")) {
continue;
}
r_cons_printf ("agn %s\n", sk);
r_cons_printf ("agn %s\n", cls->name);
r_cons_printf ("age %s %s\n", cls->super, cls->name);
r_cons_printf ("age %s %s\n", sk, cls->name);
}
}
}

View File

@ -509,7 +509,7 @@ typedef struct r_bin_section_t {
typedef struct r_bin_class_t {
char *name;
// TODO: char *module;
char *super;
RList *super; // list of char*
char *visibility_str; // XXX only used by java
int index;
ut64 addr;

View File

@ -701,25 +701,25 @@ R_API void r_bin_java_get_import_json_definitions(RBinJavaObj *bin, PJ *pj) {
R_API void r_bin_java_get_class_info_json(RBinJavaObj *bin, PJ *pj) {
r_return_if_fail (bin && pj);
RList *classes = r_bin_java_get_classes (bin);
RBinClass *class_ = r_list_get_n (classes, 0);
RBinClass *klass = r_list_get_n (classes, 0);
// pj dict already opened
if (class_) {
if (klass) {
int dummy = 0;
RListIter *iter;
RBinClass *class_v = NULL;
RBinClass *klassv = NULL;
// add access flags like in methods
bool is_public = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_PUBLIC) != 0);
bool is_final = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_FINAL) != 0);
bool is_super = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_SUPER) != 0);
bool is_interface = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0);
bool is_abstract = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ABSTRACT) != 0);
bool is_synthetic = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_SYNTHETIC) != 0);
bool is_annotation = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ANNOTATION) != 0);
bool is_enum = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ENUM) != 0);
bool is_public = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_PUBLIC) != 0);
bool is_final = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_FINAL) != 0);
bool is_super = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_SUPER) != 0);
bool is_interface = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0);
bool is_abstract = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_ABSTRACT) != 0);
bool is_synthetic = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_SYNTHETIC) != 0);
bool is_annotation = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_ANNOTATION) != 0);
bool is_enum = ((klass->visibility & R_BIN_JAVA_CLASS_ACC_ENUM) != 0);
pj_ki (pj, "access_flags", class_->visibility);
pj_ki (pj, "access_flags", klass->visibility);
pj_ki (pj, "is_public", is_public);
pj_ki (pj, "is_final", is_final);
pj_ki (pj, "is_super", is_super);
@ -728,20 +728,26 @@ R_API void r_bin_java_get_class_info_json(RBinJavaObj *bin, PJ *pj) {
pj_ki (pj, "is_synthetic", is_synthetic);
pj_ki (pj, "is_annotation", is_annotation);
pj_ki (pj, "is_enum", is_enum);
pj_ks (pj, "name", class_->name);
pj_ks (pj, "super", r_str_get (class_->super));
pj_ks (pj, "name", klass->name);
if (klass->super) {
const char *sk;
pj_ka (pj, "super");
r_list_foreach (klass->super, iter, sk) {
pj_ks (pj, "super", sk);
}
pj_end (pj);
}
pj_ka (pj, "interfaces");
r_list_foreach (classes, iter, class_v) {
r_list_foreach (classes, iter, klassv) {
if (!dummy) {
dummy++;
continue;
}
// enumerate all interface classes and append them to the interfaces
if ((class_v->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0) {
pj_s (pj, class_v->name);
if ((klassv->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0) {
pj_s (pj, klassv->name);
}
}
@ -2859,7 +2865,13 @@ R_API RList *r_bin_java_get_classes(RBinJavaObj *bin) {
k->methods = r_bin_java_enum_class_methods (bin, bin->cf2.this_class);
k->fields = r_bin_java_enum_class_fields (bin, bin->cf2.this_class);
k->name = r_bin_java_get_this_class_name (bin);
k->super = r_bin_java_get_name_from_bin_cp_list (bin, bin->cf2.super_class);
char *n = r_bin_java_get_name_from_bin_cp_list (bin, bin->cf2.super_class);
if (R_STR_ISNOTEMPTY (n)) {
k->super = r_list_newf (free);
r_list_append (k->super, n);
} else {
free (n);
}
k->index = (idx++);
k->lang = R_BIN_LANG_JAVA;
r_list_append (classes, k);

View File

@ -2,7 +2,7 @@ NAME=java prototypes in json
FILE=bins/java/jdwpexeccmd.class
CMDS=java prototypes j
EXPECT=<<EOF
{"access_flags":33,"is_public":1,"is_final":0,"is_super":1,"is_interface":0,"is_abstract":0,"is_synthetic":0,"is_annotation":0,"is_enum":0,"name":"JDWPExecCmd","super":"java/lang/Object","interfaces":[],"methods":[{"access_flags":1,"is_method":1,"is_native":0,"is_synthetic":0,"is_private":0,"is_public":1,"is_static":0,"is_protected":0,"is_super":0,"addr":825,"offset":803,"class_name":"java/lang/Object","signature":"()V","name":"<init>","fq_name":"java/lang/Object.<init>.()V","prototype":"public void <init> ()"},{"access_flags":9,"is_method":1,"is_native":0,"is_synthetic":0,"is_private":0,"is_public":1,"is_static":1,"is_protected":0,"is_super":0,"addr":868,"offset":846,"class_name":"JDWPExecCmd","signature":"(Ljava/lang/String;)Ljava/lang/String;","name":"run","fq_name":"JDWPExecCmd.run.(Ljava/lang/String;)Ljava/lang/String;","prototype":"public static java.lang.String run (java.lang.String)"}],"fields":[],"imports":["java.lang.StringBuilder","java.io.BufferedReader","java.io.InputStreamReader","java.lang.Exception","JDWPExecCmd","java.lang.Object","java.lang.String","java.lang.Process","java.io.BufferedReader","java.lang.Exception","java.lang.Runtime","java.lang.Process","java.lang.String"]}
{"access_flags":33,"is_public":1,"is_final":0,"is_super":1,"is_interface":0,"is_abstract":0,"is_synthetic":0,"is_annotation":0,"is_enum":0,"name":"JDWPExecCmd","super":["super":"java/lang/Object"],"interfaces":[],"methods":[{"access_flags":1,"is_method":1,"is_native":0,"is_synthetic":0,"is_private":0,"is_public":1,"is_static":0,"is_protected":0,"is_super":0,"addr":825,"offset":803,"class_name":"java/lang/Object","signature":"()V","name":"<init>","fq_name":"java/lang/Object.<init>.()V","prototype":"public void <init> ()"},{"access_flags":9,"is_method":1,"is_native":0,"is_synthetic":0,"is_private":0,"is_public":1,"is_static":1,"is_protected":0,"is_super":0,"addr":868,"offset":846,"class_name":"JDWPExecCmd","signature":"(Ljava/lang/String;)Ljava/lang/String;","name":"run","fq_name":"JDWPExecCmd.run.(Ljava/lang/String;)Ljava/lang/String;","prototype":"public static java.lang.String run (java.lang.String)"}],"fields":[],"imports":["java.lang.StringBuilder","java.io.BufferedReader","java.io.InputStreamReader","java.lang.Exception","JDWPExecCmd","java.lang.Object","java.lang.String","java.lang.Process","java.io.BufferedReader","java.lang.Exception","java.lang.Runtime","java.lang.Process","java.lang.String"]}
EOF
RUN

View File

@ -4217,8 +4217,8 @@ icg Hello
icg no_match
EOF
EXPECT=<<EOF
agn java/lang/Object
agn Hello
agn java/lang/Object
age java/lang/Object Hello
agn Hello
EOF