Commit message: Fix #10498 - Fix crash in fuzzed java files (#10511)
CVE: CVE-2018-14017
CWE: CWE-125
Vulnerability description: The r_bin_java_annotation_new function in shlr/java/class.c in radare2 2.7.0 allows remote attackers to cause a denial of service (heap-based buffer over-read and application crash) via a crafted .class file because of missing input validation in r_bin_java_line_number_table_attr_new.

Project: radare2
File: class.c

R_API RList *r_bin_java_find_cp_const_by_val_float(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len) {
	RList *res = r_list_newf (free);
	ut32 *v = NULL;
	RListIter *iter;
	RBinJavaCPTypeObj *cp_obj;
	eprintf ("Looking for %f\n", R_BIN_JAVA_FLOAT (bytes, 0));
	r_list_foreach (bin_obj->cp_list, iter, cp_obj) {
		if (cp_obj->tag == R_BIN_JAVA_CP_FLOAT) {
			if (len == 4 && R_BIN_JAVA_FLOAT (cp_obj->info.cp_long.bytes.raw, 0) == R_BIN_JAVA_FLOAT (bytes, 0)) {
				v = malloc (sizeof (ut32));
				if (!v) {
					r_list_free (res);
					return NULL;
				}
				*v = cp_obj->idx;
				r_list_append (res, v);
			}
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_invokedynamic_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	RBinJavaCPTypeObj *obj;
	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_INVOKEDYNAMIC, tag, sz, "RBinJavaCPTypeMethodHandle");
	if (quick_check > 0) {
		return NULL;
	}
	if ((obj = R_NEW0 (RBinJavaCPTypeObj))) {
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);;
		obj->tag = tag;
		obj->info.cp_invoke_dynamic.bootstrap_method_attr_index = R_BIN_JAVA_USHORT (buffer, 1);
		obj->info.cp_invoke_dynamic.name_and_type_index = R_BIN_JAVA_USHORT (buffer, 3);
	}
	return obj;
}

Project: radare2
File: class.c

R_API RBinJavaAttrMetas *r_bin_java_get_attr_type_by_name(const char *name) {
	// TODO: use sdb/hashtable here
	int i;
	for (i = 0; i < RBIN_JAVA_ATTRS_METAS_SZ; i++) {
		if (!strcmp ((const char *) name, RBIN_JAVA_ATTRS_METAS[i].name)) {
			return &RBIN_JAVA_ATTRS_METAS[i];
		}
	}
	return &RBIN_JAVA_ATTRS_METAS[R_BIN_JAVA_ATTR_TYPE_UNKNOWN_ATTR];
}

Project: radare2
File: class.c

R_API RBinSymbol *r_bin_java_create_new_symbol_from_fm_type_meta(RBinJavaField *fm_type, ut64 baddr) {
	RBinSymbol *sym = R_NEW0 (RBinSymbol);
	if (!sym || !fm_type || !fm_type->field_ref_cp_obj || fm_type->field_ref_cp_obj == &R_BIN_JAVA_NULL_TYPE) {
		free (sym);
		return NULL;
	}
	// ut32 new_name_len = strlen (fm_type->name) + strlen ("_meta") + 1;
	// char *new_name = malloc (new_name_len);
	sym->name = r_str_newf ("meta_%s", fm_type->name);
	if (fm_type->type == R_BIN_JAVA_FIELD_TYPE_METHOD) {
		sym->type = r_str_const ("FUNC_META");
	} else {
		sym->type = r_str_const ("FIELD_META");
	}
	if (r_bin_java_is_fm_type_protected (fm_type)) {
		sym->bind = r_str_const (R_BIN_BIND_LOCAL_STR);
	} else if (r_bin_java_is_fm_type_private (fm_type)) {
		sym->bind = r_str_const (R_BIN_BIND_LOCAL_STR);
	} else if (r_bin_java_is_fm_type_protected (fm_type)) {
		sym->bind = r_str_const (R_BIN_BIND_GLOBAL_STR);
	}
	sym->forwarder = r_str_const ("NONE");
	if (fm_type->class_name) {
		sym->classname = strdup (fm_type->class_name);
	} else {
		sym->classname = strdup ("UNKNOWN");
	}
	sym->paddr = fm_type->file_offset;// r_bin_java_get_method_code_offset (fm_type);
	sym->vaddr = fm_type->file_offset + baddr;
	sym->ordinal = fm_type->metas->ord;
	sym->size = fm_type->size;
	sym->visibility = fm_type->flags;
	if (fm_type->flags_str) {
		sym->visibility_str = strdup (fm_type->flags_str);
	}
	return sym;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_string_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_STRING, tag, sz, "String");
	if (quick_check > 0) {
		return NULL;
	}
	RBinJavaCPTypeObj *obj = R_NEW0 (RBinJavaCPTypeObj);
	if (obj) {
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
		obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
	}
	return obj;
}

Project: radare2
File: class.c

R_API int r_bin_java_is_fm_type_private(RBinJavaField *fm_type) {
	if (fm_type && fm_type->type == R_BIN_JAVA_FIELD_TYPE_METHOD) {
		return fm_type->flags & R_BIN_JAVA_METHOD_ACC_PRIVATE;
	}
	if (fm_type && fm_type->type == R_BIN_JAVA_FIELD_TYPE_FIELD) {
		return fm_type->flags & R_BIN_JAVA_FIELD_ACC_PRIVATE;
	}
	return 0;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_interfacemethodref_cp_summary(RBinJavaCPTypeObj *obj) {
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  InterfaceMethodRef.\n");
		return;
	}
	eprintf ("InterfaceMethodRef ConstantPool Type (%d) ", obj->metas->ord);
	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
	eprintf ("	Class Index = %d\n", obj->info.cp_interface.class_idx);
	eprintf ("	Name and type Index = %d\n", obj->info.cp_interface.name_and_type_idx);
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_class_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_CLASS, tag, sz, "Class");
	if (quick_check > 0) {
		return NULL;
	}
	RBinJavaCPTypeObj *obj = R_NEW0 (RBinJavaCPTypeObj);
	if (obj) {
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->info.cp_class.name_idx = R_BIN_JAVA_USHORT (buffer, 1);
	}
	return obj;
}

Project: radare2
File: class.c

R_API void r_bin_java_rtip_annotations_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) { // && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATION_ATTR) {
		r_list_free (attr->info.rtip_annotations_attr.parameter_annotations);
		free (attr->metas);
		free (attr->name);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API ut16 calculate_access_value(const char *access_flags_str, RBinJavaAccessFlags *access_flags) {
	ut16 result = 0;
	ut16 size = strlen (access_flags_str) + 1;
	char *p_flags, *my_flags = malloc (size);
	RBinJavaAccessFlags *iter = NULL;
	if (size < 5 || !my_flags) {
		free (my_flags);
		return result;
	}
	memcpy (my_flags, access_flags_str, size);
	p_flags = strtok (my_flags, " ");
	while (p_flags && access_flags) {
		int idx = 0;
		do {
			iter = &access_flags[idx];
			if (!iter || !iter->str) {
				continue;
			}
			if (iter->len > 0 && iter->len != 16) {
				if (!strncmp (iter->str, p_flags, iter->len)) {
					result |= iter->value;
				}
			}
			idx++;
		} while (access_flags[idx].str != NULL);
		p_flags = strtok (NULL, " ");
	}
	free (my_flags);
	return result;
}

Project: radare2
File: class.c

R_API void r_bin_java_rti_annotations_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_ANNOTATION_ATTR) {
		r_list_free (attr->info.annotation_array.annotations);
		free (attr->metas);
		free (attr->name);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_exceptions_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0, offset = 0;
	ut64 size;
	RBinJavaAttrInfo *attr = NULL;
	attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	if (attr == NULL) {
		// TODO eprintf
		return attr;
	}
	attr->type = R_BIN_JAVA_ATTR_TYPE_LINE_NUMBER_TABLE_ATTR;
	attr->info.exceptions_attr.number_of_exceptions = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	size = sizeof (ut16) * attr->info.exceptions_attr.number_of_exceptions;
	if (size < attr->info.exceptions_attr.number_of_exceptions) {
		free (attr);
		return NULL;
	}
	attr->info.exceptions_attr.exception_idx_table = (ut16 *) malloc (size);
	if (!attr->info.exceptions_attr.exception_idx_table) {
		free (attr);
		return NULL;
	}
	for (i = 0; i < attr->info.exceptions_attr.number_of_exceptions; i++) {
		attr->info.exceptions_attr.exception_idx_table[i] = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
	}
	attr->size = offset;
	// IFDBG r_bin_java_print_exceptions_attr_summary(attr);
	return attr;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_interfacemethodref_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_INTERFACEMETHOD_REF, tag, sz, "InterfaceMethodRef");
	if (quick_check > 0) {
		return NULL;
	}
	RBinJavaCPTypeObj *obj = R_NEW0 (RBinJavaCPTypeObj);
	if (obj) {
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
		obj->info.cp_interface.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
		obj->info.cp_interface.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);

	}
	return obj;
}

Project: radare2
File: class.c

R_API char *r_bin_java_unmangle(const char *flags, const char *name, const char *descriptor) {
	ut32 l_paren_pos = -1, r_paren_pos = -1;
	char *result = NULL;
	ut32 desc_len = descriptor && *descriptor ? strlen (descriptor) : 0,
	name_len = name && *name ? strlen (name) : 0,
	flags_len = flags && *flags ? strlen (flags) : 0,
	i = 0;
	if (desc_len == 0 || name == 0) {
		return NULL;
	}
	for (i = 0; i < desc_len; i++) {
		if (descriptor[i] == '(') {
			l_paren_pos = i;
		} else if (l_paren_pos != (ut32) - 1 && descriptor[i] == ')') {
			r_paren_pos = i;
			break;
		}
	}
	// handle field case;
	if (l_paren_pos == (ut32) - 1 && r_paren_pos == (ut32) - 1) {
		char *unmangle_field_desc = NULL;
		ut32 len = extract_type_value (descriptor, &unmangle_field_desc);
		if (len == 0) {
			eprintf ("Warning: attempting to unmangle invalid type descriptor.\n");
			free (unmangle_field_desc);
			return result;
		}
		if (flags_len > 0) {
			len += (flags_len + name_len + 5); // space and null
			result = malloc (len);
			snprintf (result, len, "%s %s %s", flags, unmangle_field_desc, name);
		} else {
			len += (name_len + 5); // space and null
			result = malloc (len);
			snprintf (result, len, "%s %s", unmangle_field_desc, name);
		}
		free (unmangle_field_desc);
	} else if (l_paren_pos != (ut32) - 1 &&
	r_paren_pos != (ut32) - 1 &&
	l_paren_pos < r_paren_pos) {
		// params_len account for l_paren + 1 and null
		ut32 params_len = r_paren_pos - (l_paren_pos + 1) != 0 ? r_paren_pos - (l_paren_pos + 1) + 1 : 0;
		char *params = params_len ? malloc (params_len) : NULL;
		const char *rvalue = descriptor + r_paren_pos + 1;
		if (params) {
			snprintf (params, params_len, "%s", descriptor + l_paren_pos + 1);
		}
		result = r_bin_java_unmangle_method (flags, name, params, rvalue);
		free (params);
	}
	return result;
}

Project: radare2
File: class.c

R_API DsoJsonObj *r_bin_java_get_field_json_definition(RBinJavaObj *bin, RBinJavaField *fm_type) {
	return r_bin_java_get_fm_type_definition_json (bin, fm_type, 0);
}

Project: radare2
File: class.c

R_API void r_bin_java_print_code_attr_summary(RBinJavaAttrInfo *attr) {
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaExceptionEntry *exc_entry = NULL;
	RBinJavaAttrInfo *_attr = NULL;
	if (!attr) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Code.\n");
		return;
	}
	Eprintf ("Code Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d, Attribute Count: %d\n", attr->length, attr->info.code_attr.attributes_count);
	Eprintf ("    Max Stack: %d\n", attr->info.code_attr.max_stack);
	Eprintf ("    Max Locals: %d\n", attr->info.code_attr.max_locals);
	Eprintf ("    Code Length: %d\n", attr->info.code_attr.code_length);
	Eprintf ("    Code At Offset: 0x%08"PFMT64x "\n", (ut64) attr->info.code_attr.code_offset);
	Eprintf ("Code Attribute Exception Table Information:\n");
	Eprintf ("  Exception Table Length: %d\n", attr->info.code_attr.exception_table_length);
	if (attr->info.code_attr.exception_table) {
		// Delete the attr entries
		r_list_foreach_safe (attr->info.code_attr.exception_table, iter, iter_tmp, exc_entry) {
			r_bin_java_print_code_exceptions_attr_summary (exc_entry);
		}
	}
	Eprintf ("  Implicit Method Stack Frame:\n");
	r_bin_java_print_stack_map_frame_summary (attr->info.code_attr.implicit_frame);
	Eprintf ("Code Attribute Attributes Information:\n");
	if (attr->info.code_attr.attributes && attr->info.code_attr.attributes_count > 0) {
		Eprintf ("  Code Attribute Attributes Count: %d\n", attr->info.code_attr.attributes_count);
		r_list_foreach_safe (attr->info.code_attr.attributes, iter, iter_tmp, _attr) {
			r_bin_java_print_attr_summary (_attr);
		}
	}
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_method_name(RBinJavaObj *bin_obj, ut32 idx) {
	char *name = NULL;
	if (idx < r_list_length (bin_obj->methods_list)) {
		RBinJavaField *fm_type = r_list_get_n (bin_obj->methods_list, idx);
		name = strdup (fm_type->name);
	}
	return name;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_desc_from_cp_item_list(RList *cp_list, ut64 idx) {
	/*
	Given a constant poool object FieldRef, MethodRef, or InterfaceMethodRef
	return the actual descriptor string.
	@rvalue ut8* (user frees) or NULL
	*/
	RBinJavaCPTypeObj *obj = r_bin_java_get_item_from_cp_item_list (cp_list, idx);
	if (cp_list == NULL) {
		return NULL;
	}
	return r_bin_java_get_item_desc_from_cp_item_list (cp_list, obj, MAX_CPITEMS);
}

Project: radare2
File: class.c

R_API void r_bin_java_rtv_annotations_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_ANNOTATION_ATTR) {
		r_list_free (attr->info.annotation_array.annotations);
		free (attr->metas);
		free (attr->name);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API ut8 *U(r_bin_java_cp_get_field_ref)(RBinJavaObj * bin, ut32 * out_sz, ut16 class_idx, ut16 name_and_type_idx) {
	return r_bin_java_cp_get_fm_ref (bin, out_sz, R_BIN_JAVA_CP_FIELDREF, class_idx, name_and_type_idx);
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_name_and_type_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	RBinJavaCPTypeObj *obj = NULL;
	int quick_check = 0;
	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_NAMEANDTYPE, tag, sz, "RBinJavaCPTypeNameAndType");
	if (quick_check > 0) {
		return obj;
	}
	obj = R_NEW0 (RBinJavaCPTypeObj);
	if (obj) {
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);;
		obj->tag = tag;
		obj->info.cp_name_and_type.name_idx = R_BIN_JAVA_USHORT (buffer, 1);
		obj->info.cp_name_and_type.descriptor_idx = R_BIN_JAVA_USHORT (buffer, 3);
	}
	return obj;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_deprecated_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaAttrInfo *attr = NULL;
	ut64 offset = 0;
	attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	if (attr) {
		attr->type = R_BIN_JAVA_ATTR_TYPE_DEPRECATED_ATTR;
		attr->size = offset;
	}
	// IFDBG r_bin_java_print_deprecated_attr_summary(attr);
	return attr;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_source_code_file_attr_summary(RBinJavaAttrInfo *attr) {
	if (!attr) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *SourceFile.\n");
		return;
	}
	Eprintf ("Source File Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
	Eprintf ("  Source File Index: %d\n", attr->info.source_file_attr.sourcefile_idx);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_get_method_start(RBinJavaObj *bin, RBinJavaField *fm_type) {
	return r_bin_java_get_method_code_offset (fm_type) + bin->loadaddr;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_find_cp_ref_info(RBinJavaObj *bin, ut16 name_and_type_idx) {
	RListIter *iter, *iter_tmp;
	RBinJavaCPTypeObj *res = NULL, *obj = NULL;
	r_list_foreach_safe (bin->cp_list, iter, iter_tmp, obj) {
		if (obj->tag == R_BIN_JAVA_CP_FIELDREF &&
		obj->info.cp_field.name_and_type_idx == name_and_type_idx) {
			res = obj;
			break;
		} else if (obj->tag == R_BIN_JAVA_CP_METHODREF &&
		obj->info.cp_method.name_and_type_idx == name_and_type_idx) {
			res = obj;
			break;
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_element_value_calc_size(RBinJavaElementValue *element_value) {
	RListIter *iter, *iter_tmp;
	RBinJavaElementValue *ev_element;
	RBinJavaElementValuePair *ev_pairs;
	ut64 sz = 0;
	if (element_value == NULL) {
		return sz;
	}
	// tag
	sz += 1;
	switch (element_value->tag) {
	case R_BIN_JAVA_EV_TAG_BYTE:
	case R_BIN_JAVA_EV_TAG_CHAR:
	case R_BIN_JAVA_EV_TAG_DOUBLE:
	case R_BIN_JAVA_EV_TAG_FLOAT:
	case R_BIN_JAVA_EV_TAG_INT:
	case R_BIN_JAVA_EV_TAG_LONG:
	case R_BIN_JAVA_EV_TAG_SHORT:
	case R_BIN_JAVA_EV_TAG_BOOLEAN:
	case R_BIN_JAVA_EV_TAG_STRING:
		// look up value in bin->cp_list
		// (ut16) read and set const_value.const_value_idx
		// element_value->value.const_value.const_value_idx = r_bin_java_read_short(bin, bin->b->cur);
		sz += 2;
		break;
	case R_BIN_JAVA_EV_TAG_ENUM:
		// (ut16) read and set enum_const_value.type_name_idx
		// element_value->value.enum_const_value.type_name_idx = r_bin_java_read_short(bin, bin->b->cur);
		sz += 2;
		// (ut16) read and set enum_const_value.const_name_idx
		// element_value->value.enum_const_value.const_name_idx = r_bin_java_read_short(bin, bin->b->cur);
		sz += 2;
		break;
	case R_BIN_JAVA_EV_TAG_CLASS:
		// (ut16) read and set class_value.class_info_idx
		// element_value->value.class_value.class_info_idx = r_bin_java_read_short(bin, bin->b->cur);
		sz += 2;
		break;
	case R_BIN_JAVA_EV_TAG_ARRAY:
		// (ut16) read and set array_value.num_values
		// element_value->value.array_value.num_values = r_bin_java_read_short(bin, bin->b->cur);
		sz += 2;
		r_list_foreach_safe (element_value->value.array_value.values, iter, iter_tmp, ev_element) {
			if (ev_element) {
				sz += r_bin_java_element_value_calc_size (ev_element);
			}
		}
		break;
	case R_BIN_JAVA_EV_TAG_ANNOTATION:
		// annotation new is not used here.
		// (ut16) read and set annotation_value.type_idx;
		// element_value->value.annotation_value.type_idx = r_bin_java_read_short(bin, bin->b->cur);
		sz += 2;
		// (ut16) read and set annotation_value.num_element_value_pairs;
		// element_value->value.annotation_value.num_element_value_pairs = r_bin_java_read_short(bin, bin->b->cur);
		sz += 2;
		element_value->value.annotation_value.element_value_pairs = r_list_newf (r_bin_java_element_pair_free);
		r_list_foreach_safe (element_value->value.annotation_value.element_value_pairs, iter, iter_tmp, ev_pairs) {
			if (ev_pairs) {
				sz += r_bin_java_element_pair_calc_size (ev_pairs);
			}
		}
		break;
	default:
		// eprintf unable to handle tag
		break;
	}
	return sz;
}

Project: radare2
File: class.c

R_API void r_bin_java_bootstrap_methods_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_BOOTSTRAP_METHODS_ATTR) {
		free (attr->name);
		free (attr->metas);
		r_list_free (attr->info.bootstrap_methods_attr.bootstrap_methods);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_long_cp_summary(RBinJavaCPTypeObj *obj) {
	ut8 *b = NULL;
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Long.\n");
		return;
	}
	b = obj->info.cp_long.bytes.raw;
	Eprintf ("Long ConstantPool Type (%d) ", obj->metas->ord);
	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
	Eprintf ("  High-Bytes = %02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
	Eprintf ("  Low-Bytes = %02x %02x %02x %02x\n", b[4], b[5], b[6], b[7]);
	Eprintf ("  Long = %08"PFMT64x "\n", r_bin_java_raw_to_long (obj->info.cp_long.bytes.raw, 0));
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_invokedynamic_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			obj->info.cp_invoke_dynamic.bootstrap_method_attr_index,
			obj->info.cp_invoke_dynamic.name_and_type_index);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					obj->info.cp_invoke_dynamic.bootstrap_method_attr_index,
					obj->info.cp_invoke_dynamic.name_and_type_index);
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API RBinAddr *r_bin_java_get_entrypoint(RBinJavaObj *bin, int sym) {
	RBinAddr *ret = NULL;
	ret = R_NEW0 (RBinAddr);
	if (!ret) {
		return NULL;
	}
	ret->paddr = UT64_MAX;
	switch (sym) {
	case R_BIN_SYM_ENTRY:
	case R_BIN_SYM_INIT:
		ret->paddr = r_bin_java_find_method_offset (bin, "<init>");
		if (ret->paddr == UT64_MAX) {
			ret->paddr = r_bin_java_find_method_offset (bin, "<cinit>");
		}
		break;
	case R_BIN_SYM_FINI:
		ret->paddr = UT64_MAX;
		break;
	case R_BIN_SYM_MAIN:
		ret->paddr = r_bin_java_find_method_offset (bin, "main");
		break;
	default:
		ret->paddr = -1;
	}
	if (ret->paddr != -1) {
		ret->paddr += bin->loadaddr;
	}
	return ret;
}

Project: radare2
File: class.c

R_API RBinJavaAnnotationsArray *r_bin_java_annotation_array_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaAnnotation *annotation;
	RBinJavaAnnotationsArray *annotation_array;
	ut32 i;
	ut64 offset = 0;
	annotation_array = (RBinJavaAnnotationsArray *) malloc (sizeof (RBinJavaAnnotationsArray));
	if (annotation_array == NULL) {
		// TODO eprintf
		return NULL;
	}
	annotation_array->num_annotations = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	annotation_array->annotations = r_list_new ();
	for (i = 0; i < annotation_array->num_annotations; i++) {
		annotation = r_bin_java_annotation_new (buffer + offset, sz - offset, buf_offset + offset);
		if (annotation) {
			offset += annotation->size;
		}
		if (annotation == NULL) {
			// TODO eprintf
		}
		r_list_append (annotation_array->annotations, (void *) annotation);
	}
	annotation_array->size = offset;
	return annotation_array;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_fieldref_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	RBinJavaCPTypeObj *obj = NULL;
	int quick_check = 0;
	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_FIELDREF, tag, sz, "FieldRef");
	if (quick_check > 0) {
		return obj;
	}
	obj = (RBinJavaCPTypeObj *) malloc (sizeof (RBinJavaCPTypeObj));
	if (obj) {
		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->info.cp_field.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
		obj->info.cp_field.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);

	}
	return (RBinJavaCPTypeObj *) obj;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_enum_class_fields(RBinJavaObj *bin, ut16 class_idx) {
	RList *fields = r_list_newf (free);
	RListIter *iter;
	RBinJavaField *fm_type;
	RBinField *field = NULL;
	r_list_foreach (bin->fields_list, iter, fm_type) {
		if (fm_type) {
			if (fm_type && fm_type->field_ref_cp_obj
			&& fm_type->field_ref_cp_obj->metas->ord == class_idx) {
				field = r_bin_java_create_new_rbinfield_from_field (fm_type, bin->loadaddr);
				if (field) {
					r_list_append (fields, field);
				}
			}
		}
	}
	return fields;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_element_value_summary(RBinJavaElementValue *element_value) {
	RBinJavaCPTypeObj *obj;
	RBinJavaElementValue *ev_element = NULL;
	RListIter *iter = NULL, *iter_tmp = NULL;
	char *name;
	if (element_value == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaElementValuePair *pair.\n");
		return;
	}
	name = ((RBinJavaElementValueMetas *) element_value->metas->type_info)->name;
	eprintf ("Element Value information:\n");
	eprintf ("   EV Pair File Offset: 0x%08"PFMT64x "\n", element_value->file_offset);
	eprintf ("   EV Value Type (%d): %s\n", element_value->tag, name);
	switch (element_value->tag) {
	case R_BIN_JAVA_EV_TAG_BYTE:
	case R_BIN_JAVA_EV_TAG_CHAR:
	case R_BIN_JAVA_EV_TAG_DOUBLE:
	case R_BIN_JAVA_EV_TAG_FLOAT:
	case R_BIN_JAVA_EV_TAG_INT:
	case R_BIN_JAVA_EV_TAG_LONG:
	case R_BIN_JAVA_EV_TAG_SHORT:
	case R_BIN_JAVA_EV_TAG_BOOLEAN:
	case R_BIN_JAVA_EV_TAG_STRING:
		eprintf ("   EV Value Constant Value index: 0x%02x\n", element_value->value.const_value.const_value_idx);
		eprintf ("   EV Value Constant Value Information:\n");
		obj = element_value->value.const_value.const_value_cp_obj;
		((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->print_summary (obj);
		break;
	case R_BIN_JAVA_EV_TAG_ENUM:
		eprintf ("   EV Value Enum Constant Value Const Name Index: 0x%02x\n", element_value->value.enum_const_value.const_name_idx);
		eprintf ("   EV Value Enum Constant Value Type Name Index: 0x%02x\n", element_value->value.enum_const_value.type_name_idx);
		eprintf ("   EV Value Enum Constant Value Const CP Information:\n");
		obj = element_value->value.enum_const_value.const_name_cp_obj;
		((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->print_summary (obj);
		eprintf ("   EV Value Enum Constant Value Type CP Information:\n");
		obj = element_value->value.enum_const_value.type_name_cp_obj;
		((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->print_summary (obj);
		break;
	case R_BIN_JAVA_EV_TAG_CLASS:
		eprintf ("   EV Value Class Info Index: 0x%02x\n", element_value->value.class_value.class_info_idx);
		eprintf ("   EV Value Class Info CP Information:\n");
		obj = element_value->value.class_value.class_info_cp_obj;
		((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->print_summary (obj);
		break;
	case R_BIN_JAVA_EV_TAG_ARRAY:
		eprintf ("   EV Value Array Value Number of Values: 0x%04x\n", element_value->value.array_value.num_values);
		eprintf ("   EV Value Array Values\n");
		r_list_foreach_safe (element_value->value.array_value.values, iter, iter_tmp, ev_element) {
			r_bin_java_print_element_value_summary (ev_element);
		}
		break;
	case R_BIN_JAVA_EV_TAG_ANNOTATION:
		eprintf ("   EV Annotation Information:\n");
		r_bin_java_print_annotation_summary (&element_value->value.annotation_value);
		break;
	default:
		// eprintf unable to handle tag
		break;
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_methodref_cp_summary(RBinJavaCPTypeObj *obj) {
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  MethodRef.\n");
		return;
	}
	eprintf ("MethodRef ConstantPool Type (%d) ", obj->metas->ord);
	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
	eprintf ("	Class Index = %d\n", obj->info.cp_method.class_idx);
	eprintf ("	Name and type Index = %d\n", obj->info.cp_method.name_and_type_idx);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_resolve_cp_idx_address(RBinJavaObj *BIN_OBJ, int idx) {
	RBinJavaCPTypeObj *item = NULL;
	ut64 addr = -1;
	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
		return -1;
	}
	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
	if (item) {
		addr = item->file_offset + item->loadaddr;
	}
	return addr;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_ret(RBinJavaField *fm_type) {
	RList *the_list = r_bin_java_extract_type_values (fm_type->descriptor);
	RList *ret_list = r_list_new ();
	ut8 in_ret = 0;
	RListIter *desc_iter;
	char *str;
	r_list_foreach (the_list, desc_iter, str) {
		if (str && *str != ')') {
			in_ret = 0;
		}
		if (in_ret) {
			r_list_append (ret_list, strdup (str));
		}
	}
	r_list_free (the_list);
	return ret_list;
}

Project: radare2
File: class.c

R_API RBinJavaInterfaceInfo *r_bin_java_interface_new(RBinJavaObj *bin, const ut8 *buffer, ut64 sz) {
	RBinJavaInterfaceInfo *ifobj = NULL;
	ifobj = R_NEW0 (RBinJavaInterfaceInfo);
	IFDBG eprintf("Parsing RBinJavaInterfaceInfo\n");
	if (ifobj) {
		if (buffer) {
			ifobj->class_info_idx = R_BIN_JAVA_USHORT (buffer, 0);
			ifobj->cp_class = r_bin_java_get_item_from_bin_cp_list (bin, ifobj->class_info_idx);
			if (ifobj->cp_class) {
				ifobj->name = r_bin_java_get_item_name_from_bin_cp_list (bin, ifobj->cp_class);
			} else {
				ifobj->name = r_str_dup (NULL, "NULL");
			}
			ifobj->size = 2;
		} else {
			ifobj->class_info_idx = 0;
			ifobj->name = r_str_dup (NULL, "NULL");
		}
	}
	return ifobj;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_parse_cp_pool(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
	int ord = 0;
	ut64 adv = 0;
	RBinJavaCPTypeObj *obj = NULL;
	const ut8 *cp_buf = buf + offset;
	r_list_free (bin->cp_list);
	bin->cp_list = r_list_newf (r_bin_java_constant_pool);
	bin->cp_offset = offset;
	memcpy ((char *) &bin->cp_count, cp_buf, 2);
	bin->cp_count = R_BIN_JAVA_USHORT (cp_buf, 0) - 1;
	adv += 2;
	IFDBG eprintf("ConstantPoolCount %d\n", bin->cp_count);
	r_list_append (bin->cp_list, r_bin_java_get_java_null_cp ());
	for (ord = 1, bin->cp_idx = 0; bin->cp_idx < bin->cp_count && adv < len; ord++, bin->cp_idx++) {
		obj = r_bin_java_read_next_constant_pool_item (bin, offset + adv, buf, len);
		if (obj) {
			// IFDBG eprintf ("SUCCESS Read ConstantPoolItem %d\n", i);
			obj->metas->ord = ord;
			obj->idx = ord;
			r_list_append (bin->cp_list, obj);
			if (obj->tag == R_BIN_JAVA_CP_LONG || obj->tag == R_BIN_JAVA_CP_DOUBLE) {
				// i++;
				ord++;
				bin->cp_idx++;
				r_list_append (bin->cp_list, &R_BIN_JAVA_NULL_TYPE);
			}

			IFDBG ((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->print_summary (obj);
			adv += ((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->calc_size (obj);
			if (offset + adv > len) {
				eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Constant Pool Object: %d.\n", ord);
				break;
			}
		} else {
			IFDBG eprintf("Failed to read ConstantPoolItem %d\n", bin->cp_idx);
			break;
		}
	}
	// Update the imports
	r_bin_java_set_imports (bin);
	bin->cp_size = adv;
	return bin->cp_size;
}

Project: radare2
File: class.c

R_API char *retrieve_field_access_string(ut16 flags) {
	return retrieve_access_string (flags, FIELD_ACCESS_FLAGS);
}

Project: radare2
File: class.c

R_API void r_bin_add_import(RBinJavaObj *bin, RBinJavaCPTypeObj *obj, const char *type) {
	RBinImport *imp = R_NEW0 (RBinImport);
	char *class_name = r_bin_java_get_name_from_bin_cp_list (bin, obj->info.cp_method.class_idx);
	char *name = r_bin_java_get_name_from_bin_cp_list (bin, obj->info.cp_method.name_and_type_idx);
	char *descriptor = r_bin_java_get_desc_from_bin_cp_list (bin, obj->info.cp_method.name_and_type_idx);
	class_name = class_name ? class_name : strdup ("INVALID CLASS NAME INDEX");
	name = name ? name : strdup ("InvalidNameIndex");
	descriptor = descriptor ? descriptor : strdup ("INVALID DESCRIPTOR INDEX");
	imp->classname = class_name;
	imp->name = name;
	imp->bind = r_str_const ("NONE");
	imp->type = r_str_const (type);
	imp->descriptor = descriptor;
	imp->ordinal = obj->idx;
	r_list_append (bin->imports_list, imp);
}

Project: radare2
File: class.c

R_API double my_pow(ut64 base, int exp) {
	ut8 flag = 0;
	ut64 res = 1;
	if (exp < 0) {
		flag = 1;
		exp *= -1;
	}
	while (exp) {
		if (exp & 1) {
			res *= base;
		}
		exp >>= 1;
		base *= base;
		IFDBG eprintf("Result: %"PFMT64d ", base: %"PFMT64d ", exp: %d\n", res, base, exp);
	}
	if (flag == 0) {
		return 1.0 * res;
	}
	return (1.0 / res);
}

Project: radare2
File: class.c

R_API void r_bin_java_print_string_cp_summary(RBinJavaCPTypeObj *obj) {
	if (!obj) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  String.\n");
		return;
	}
	Eprintf ("String ConstantPool Type (%d) ", obj->metas->ord);
	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
	Eprintf ("  String Index = %d\n", obj->info.cp_string.string_idx);
}

Project: radare2
File: class.c

R_API ut32 r_bin_java_get_utf8_len_from_cp_item_list(RList *cp_list, ut64 idx) {
	/*
	Search through the Constant Pool list for the given CP Index.
	If the idx not found by directly going to the list index,
	the list will be walked and then the IDX will be checked.
	rvalue: new ut32 .
	*/
	ut32 value = -1;
	RListIter *iter;
	RBinJavaCPTypeObj *item = NULL;
	if (cp_list == NULL) {
		return 0;
	}
	item = (RBinJavaCPTypeObj *) r_list_get_n (cp_list, idx);
	if (item && (item->tag == R_BIN_JAVA_CP_UTF8) && item->metas->ord == idx) {
		value = item->info.cp_utf8.length;
	}
	if (value == -1) {
		r_list_foreach (cp_list, iter, item) {
			if (item && (item->tag == R_BIN_JAVA_CP_UTF8) && item->metas->ord == idx) {
				value = item->info.cp_utf8.length;
				break;
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_stack_map_table_attr_summary(RBinJavaAttrInfo *attr) {
	RListIter *iter, *iter_tmp;
	RList *ptrList;
	RBinJavaStackMapFrame *frame;
	if (attr == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaStackMapTableAttr*  .\n");
		return;
	}
	Eprintf ("StackMapTable Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
	Eprintf ("  StackMapTable Method Code Size: 0x%08x\n", attr->info.stack_map_table_attr.code_size);
	Eprintf ("  StackMapTable Frame Entries: 0x%08x\n", attr->info.stack_map_table_attr.number_of_entries);
	Eprintf ("  StackMapTable Frames:\n");
	ptrList = attr->info.stack_map_table_attr.stack_map_frame_entries;
	if (ptrList) {
		r_list_foreach_safe (ptrList, iter, iter_tmp, frame) {
			r_bin_java_print_stack_map_frame_summary (frame);
		}
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_rti_annotations_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 0;
	if (attr == NULL) {
		// TODO eprintf allocation fail
		return size;
	}
	size += (6 + r_bin_java_annotation_array_calc_size (&(attr->info.annotation_array)));
	return size;
}

Project: radare2
File: class.c

R_API int U(r_bin_java_double_cp_set)(RBinJavaObj * bin, ut16 idx, ut32 val) {
	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	if (!cp_obj) {
		return false;
	}
	ut8 bytes[8] = {
		0
	};
	if (cp_obj->tag != R_BIN_JAVA_CP_LONG && cp_obj->tag != R_BIN_JAVA_CP_DOUBLE) {
		eprintf ("Not supporting the overwrite of CP Objects with one of a different size.\n");
		return false;
	}
	r_bin_java_check_reset_cp_obj (cp_obj, R_BIN_JAVA_CP_DOUBLE);
	cp_obj->tag = R_BIN_JAVA_CP_DOUBLE;
	ut64 val64 = val;
	memcpy (bytes, (const char *) &val64, 8);
	val64 = r_bin_java_raw_to_long (bytes, 0);
	memcpy (&cp_obj->info.cp_double.bytes.raw, (const char *) &val64, 8);
	return true;
}

Project: radare2
File: class.c

R_API RBinJavaObj *r_bin_java_new_buf(RBuffer *buf, ut64 loadaddr, Sdb *kv) {
	RBinJavaObj *bin = R_NEW0 (RBinJavaObj);
	if (!bin) {
		return NULL;
	}
	if (!r_bin_java_new_bin (bin, loadaddr, kv, buf->buf, buf->length)) {
		return r_bin_java_free (bin);
	}
	return bin;
}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_get_idx_bytes(RBinJavaObj *bin, ut16 idx, ut32 *out_sz) {
	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	if (!cp_obj || !out_sz) {
		return NULL;
	}
	if (out_sz) {
		*out_sz = 0;
	}
	switch (cp_obj->tag) {
	case R_BIN_JAVA_CP_INTEGER:
	case R_BIN_JAVA_CP_FLOAT:
		return r_bin_java_cp_get_4bytes (cp_obj->tag, out_sz, cp_obj->info.cp_integer.bytes.raw, 5);
	case R_BIN_JAVA_CP_LONG:
	case R_BIN_JAVA_CP_DOUBLE:
		return r_bin_java_cp_get_4bytes (cp_obj->tag, out_sz, cp_obj->info.cp_long.bytes.raw, 9);
	case R_BIN_JAVA_CP_UTF8:
		// eprintf ("Getting idx: %d = %p (3+0x%"PFMT64x")\n", idx, cp_obj, cp_obj->info.cp_utf8.length);
		if (cp_obj->info.cp_utf8.length > 0) {
			return r_bin_java_cp_get_utf8 (cp_obj->tag, out_sz,
				cp_obj->info.cp_utf8.bytes, cp_obj->info.cp_utf8.length);
		}
	}
	return NULL;
}

Project: radare2
File: class.c

R_API char *r_bin_java_unmangle_method(const char *flags, const char *name, const char *params, const char *r_value) {
	RList *the_list = params ? r_bin_java_extract_type_values (params) : r_list_new ();
	RListIter *iter = NULL;
	// second case removes leading space if no flags are given
	const char *fmt = flags ? "%s %s %s (%s)" : "%s%s %s (%s)";
	char *str = NULL, *f_val_str = NULL, *r_val_str = NULL, *prototype = NULL, *p_val_str = NULL;
	ut32 params_idx = 0, params_len = 0, prototype_len = 0;
	if (!extract_type_value (r_value, &r_val_str)) {
		r_list_free (the_list);
		return NULL;
	}
	if (!r_val_str) {
		r_val_str = strdup ("UNKNOWN");
	}
	f_val_str = strdup (flags ? flags : "");
	params_idx = 0;
	r_list_foreach (the_list, iter, str) {
		params_len += strlen (str);
		if (params_idx > 0) {
			params_len += 2;
		}
		params_idx++;
	}
	if (params_len > 0) {
		ut32 offset = 0;
		params_len += 1;
		p_val_str = malloc (params_len);
		params_idx = 0;
		r_list_foreach (the_list, iter, str) {
			if (offset != 0) {
				offset += snprintf (p_val_str + offset, params_len - offset, ", %s", str);
			} else {
				offset += snprintf (p_val_str + offset, params_len - offset, "%s", str);
			}
		}
	} else {
		p_val_str = strdup ("");
	}

	prototype_len += (flags ? strlen (flags) + 1 : 0); // space vs no space
	prototype_len += strlen (name) + 1; // name + space
	prototype_len += strlen (r_val_str) + 1; // r_value + space
	prototype_len += strlen (p_val_str) + 3; // space + l_paren + params + r_paren
	prototype_len += 1; // null
	prototype = malloc (prototype_len);
	/// TODO enable this function and start using it to demangle strings
	snprintf (prototype, prototype_len, fmt, f_val_str, r_val_str, name, p_val_str);
	free (f_val_str);
	free (r_val_str);
	free (p_val_str);
	r_list_free (the_list);
	return prototype;
}

Project: radare2
File: class.c

R_API void UNUSED_FUNCTION(r_bin_java_print_prototypes)(RBinJavaObj * bin) {
	RList *the_list = r_bin_java_get_method_definitions (bin);
	RListIter *iter;
	char *str;
	r_list_foreach (the_list, iter, str) {
		eprintf ("%s;\n", str);
	}
	r_list_free (the_list);
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_default_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	// NOTE: this function receives the buffer offset in the original buffer,
	// but the buffer is already point to that particular offset.
	// XXX - all the code that relies on this function should probably be modified
	// so that the original buffer pointer is passed in and then the buffer+buf_offset
	// points to the correct location.
	RBinJavaAttrInfo *attr = R_NEW0 (RBinJavaAttrInfo);
	if (!attr) {
		return NULL;
	}
	RBinJavaAttrMetas *type_info = NULL;
	attr->metas = R_NEW0 (RBinJavaMetaInfo);
	if (attr->metas == NULL) {
		free (attr);
		return NULL;
	}
	attr->file_offset = buf_offset;
	attr->name_idx = R_BIN_JAVA_USHORT (buffer, 0);
	attr->length = R_BIN_JAVA_UINT (buffer, 2);
	attr->size = R_BIN_JAVA_UINT (buffer, 2) + 6;
	attr->name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, attr->name_idx);
	if (attr->name == NULL) {
		// Something bad has happened
		attr->name = r_str_dup (NULL, "NULL");
		eprintf ("r_bin_java_default_attr_new: Unable to find the name for %d index.\n", attr->name_idx);
	}
	type_info = r_bin_java_get_attr_type_by_name (attr->name);
	attr->metas->ord = (R_BIN_JAVA_GLOBAL_BIN->attr_idx++);
	attr->metas->type_info = (void *) type_info;
	// IFDBG eprintf ("	Addrs for type_info [tag=%d]: 0x%08"PFMT64x"\n", type_val, &attr->metas->type_info);
	return attr;
}

Project: radare2
File: class.c

R_API ut32 r_bin_java_get_method_count(RBinJavaObj *bin_obj) {
	return r_list_length (bin_obj->methods_list);
}

Project: radare2
File: class.c

R_API RList *r_bin_java_find_cp_const_by_val_double(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len) {
	RList *res = r_list_newf (free);
	ut32 *v = NULL;
	RListIter *iter;
	RBinJavaCPTypeObj *cp_obj;
	eprintf ("Looking for %f\n", r_bin_java_raw_to_double (bytes, 0));
	r_list_foreach (bin_obj->cp_list, iter, cp_obj) {
		if (cp_obj->tag == R_BIN_JAVA_CP_DOUBLE) {
			if (len == 8 && r_bin_java_raw_to_double (cp_obj->info.cp_long.bytes.raw, 0) == r_bin_java_raw_to_double (bytes, 0)) {
				v = malloc (sizeof (ut32));
				if (!v) {
					r_list_free (res);
					return NULL;
				}
				*v = cp_obj->idx;
				r_list_append (res, v);
			}
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_interfacemethodref_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	// tag
	size += 1;
	// obj->info.cp_interface.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
	size += 2;
	// obj->info.cp_interface.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);
	size += 2;
	return size;
}

Project: radare2
File: class.c

R_API ut8 *U(r_bin_java_cp_append_method_ref)(RBinJavaObj * bin, ut32 * out_sz, ut16 cn_idx, ut16 fn_idx, ut16 ft_idx) {
	return r_bin_java_cp_get_fref_bytes (bin, out_sz, R_BIN_JAVA_CP_METHODREF, cn_idx, fn_idx, ft_idx);
}

Project: radare2
File: class.c

R_API RBinSymbol *r_bin_java_create_new_symbol_from_invoke_dynamic(RBinJavaCPTypeObj *obj, ut64 baddr) {
	if (!obj || (obj->tag != R_BIN_JAVA_CP_INVOKEDYNAMIC)) {
		return NULL;
	}
	return r_bin_java_create_new_symbol_from_cp_idx (obj->info.cp_invoke_dynamic.name_and_type_index, baddr);
}

Project: radare2
File: class.c

R_API DsoJsonObj *r_bin_java_get_method_json_definition(RBinJavaObj *bin, RBinJavaField *fm_type) {
	return r_bin_java_get_fm_type_definition_json (bin, fm_type, 1);
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_item_desc_from_cp_item_list(RList *cp_list, RBinJavaCPTypeObj *obj, int depth) {
	/*
	Given a constant poool object FieldRef, MethodRef, or InterfaceMethodRef
	return the actual descriptor string.
	@rvalue ut8* (user frees) or NULL
	*/
	if (!obj || !cp_list || depth < 0) {
		return NULL;
	}
	switch (obj->tag) {
	case R_BIN_JAVA_CP_NAMEANDTYPE:
		return r_bin_java_get_utf8_from_cp_item_list (cp_list,
			obj->info.cp_name_and_type.descriptor_idx);
	// XXX - Probably not good form, but they are the same memory structure
	case R_BIN_JAVA_CP_FIELDREF:
	case R_BIN_JAVA_CP_INTERFACEMETHOD_REF:
	case R_BIN_JAVA_CP_METHODREF:
		obj = r_bin_java_get_item_from_cp_item_list (cp_list,
			obj->info.cp_method.name_and_type_idx);
		return r_bin_java_get_item_desc_from_cp_item_list (
			cp_list, obj, depth - 1);
	default:
		return NULL;
	}
	return NULL;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_methodtype_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	size += 1;
	// obj->info.cp_method_type.descriptor_index = R_BIN_JAVA_USHORT (buffer, 1);
	size += 2;
	return size;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_signature_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 0;
	if (attr == NULL) {
		// TODO eprintf allocation fail
		return size;
	}
	size += 6;
	// attr->info.source_file_attr.sourcefile_idx = R_BIN_JAVA_USHORT (buffer, offset);
	size += 2;
	// attr->info.signature_attr.signature_idx = R_BIN_JAVA_USHORT (buffer, offset);
	size += 2;
	return size;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_local_variable_type_table_attr_calc_size(RBinJavaAttrInfo *attr) {
	// RBinJavaLocalVariableTypeAttribute *lvattr;
	RListIter *iter;
	ut64 size = 0;
	if (attr) {
		RList *list = attr->info.local_variable_type_table_attr.local_variable_table;
		size += 6;
		// attr->info.local_variable_type_table_attr.table_length = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// r_list_foreach (list, iter, lvattr) {
		r_list_foreach_iter (list, iter) {
			// lvattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
			// lvattr->length = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
			// lvattr->name_idx = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
			// lvattr->signature_idx = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
			// lvattr->index = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
		}
	}
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_signature_attr_summary(RBinJavaAttrInfo *attr) {
	if (!attr) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *SignatureAttr.\n");
		return;
	}
	Eprintf ("Signature Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
	Eprintf ("  Signature UTF8 Index: %d\n", attr->info.signature_attr.signature_idx);
	Eprintf ("  Signature string: %s\n", attr->info.signature_attr.signature);
}

Project: radare2
File: class.c

R_API void r_bin_java_bootstrap_method_free(void /*/RBinJavaBootStrapMethod*/ *b) {
	RBinJavaBootStrapMethod *bsm = b;
	RListIter *iter, *iter_tmp;
	RBinJavaBootStrapArgument *obj = NULL;
	if (bsm) {
		if (bsm->bootstrap_arguments) {
			r_list_foreach_safe (bsm->bootstrap_arguments, iter, iter_tmp, obj) {
				if (obj) {
					r_bin_java_bootstrap_method_argument_free (obj);
				}
				// r_list_delete (bsm->bootstrap_arguments, iter);
			}
			r_list_free (bsm->bootstrap_arguments);
			bsm->bootstrap_arguments = NULL;
		}
		free (bsm);
	}
}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_get_fref_bytes(RBinJavaObj *bin, ut32 *out_sz, ut8 tag, ut16 cn_idx, ut16 fn_idx, ut16 ft_idx) {
	ut8 *bytes = NULL, *fnt_bytes = NULL;
	RBinJavaCPTypeObj *ref_cp_obj = NULL;
	ut16 fnt_idx = 0, cref_idx = 0;
	ut32 fnt_len = 0;
	ut16 ref_cp_obj_idx = r_bin_java_find_cp_class_ref_from_name_idx (bin, cn_idx);
	if (!ref_cp_obj_idx) {
		return NULL;
	}
	ref_cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, ref_cp_obj_idx);
	if (ref_cp_obj) {
		cref_idx = ref_cp_obj->idx;
	}
	ref_cp_obj = r_bin_java_find_cp_name_and_type_info (bin, fn_idx, ft_idx);
	if (ref_cp_obj) {
		fnt_idx = ref_cp_obj->idx;
	} else {
		fnt_bytes = r_bin_java_cp_get_name_type (bin, &fnt_len, fn_idx, ft_idx);
		fnt_idx = bin->cp_idx + 1;
	}
	if (cref_idx && fnt_idx) {
		bytes = r_bin_java_cp_get_fm_ref (bin, out_sz, tag, cref_idx, fnt_idx);
		if (fnt_bytes) {
			ut8 *tbuf = malloc (fnt_len + *out_sz);
			if (!tbuf) {
				free (bytes);
				free (fnt_bytes);
				return NULL;
			}
			// copy the bytes to the new buffer
			memcpy (tbuf, fnt_bytes, fnt_len);
			memcpy (tbuf + fnt_len, bytes, *out_sz);
			// update the values free old buffer
			*out_sz += fnt_len;
			free (bytes);
			bytes = tbuf;
		}
	}
	free (fnt_bytes);
	return bytes;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_code_exceptions_attr_summary(RBinJavaExceptionEntry *exc_entry) {
	if (exc_entry == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaExceptionEntry *.\n");
		return;
	}
	Eprintf ("  Exception Table Entry Information\n");
	Eprintf ("    offset:	0x%08"PFMT64x"\n", exc_entry->file_offset);
	Eprintf ("    catch_type: %d\n", exc_entry->catch_type);
	Eprintf ("    start_pc:   0x%04x\n", exc_entry->start_pc);
	Eprintf ("    end_pc:	0x%04x\n", exc_entry->end_pc);
	Eprintf ("    handler_pc: 0x%04x\n", exc_entry->handler_pc);
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeMetas *U(r_bin_java_get_cp_meta_from_tag)(ut8 tag) {
	ut16 i = 0;
	// set default to unknown.
	RBinJavaCPTypeMetas *res = &R_BIN_JAVA_CP_METAS[2];
	for (i = 0; i < R_BIN_JAVA_CP_METAS_SZ; i++) {
		if (tag == R_BIN_JAVA_CP_METAS[i].tag) {
			res = &R_BIN_JAVA_CP_METAS[i];
			break;
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_float_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	RBinJavaCPTypeObj *obj = NULL;
	int quick_check = 0;
	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_FLOAT, tag, sz, "Float");
	if (quick_check > 0) {
		return obj;
	}
	obj = (RBinJavaCPTypeObj *) calloc (1, sizeof (RBinJavaCPTypeObj));
	if (obj) {
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
		memset (&obj->info.cp_float.bytes, 0, sizeof (obj->info.cp_float.bytes));
		memcpy (&obj->info.cp_float.bytes.raw, buffer, 4);
	}
	return (RBinJavaCPTypeObj *) obj;
}

Project: radare2
File: class.c

R_API int r_bin_java_print_field_idx_summary(RBinJavaObj *bin_obj, ut32 idx) {
	int res = false;
	if (idx < r_list_length (bin_obj->fields_list)) {
		RBinJavaField *fm_type = r_list_get_n (bin_obj->fields_list, idx);
		r_bin_java_print_field_summary (fm_type);
		res = true;
	}
	return res;
}

Project: radare2
File: class.c

R_API int extract_type_value(const char *arg_str, char **output) {
	ut8 found_one = 0, array_cnt = 0;
	ut32 len = 0, consumed = 0;
	char *str = NULL;
	if (!arg_str || !output) {
		return 0;
	}
	if (output && *output && *output != NULL) {
		free (*output);
		*output = NULL;
	}
	while (arg_str && *arg_str && !found_one) {
		len = 0;
		// handle the end of an object
		switch (*arg_str) {
		case 'V':
			len = 1;
			str = get_type_value_str ("void", array_cnt);
			break;
		case 'J':
			len = 1;
			str = get_type_value_str ("long", array_cnt);
			array_cnt = 0;
			break;
		case 'I':
			len = 1;
			str = get_type_value_str ("int", array_cnt);
			array_cnt = 0;
			break;
		case 'D':
			len = 1;
			str = get_type_value_str ("double", array_cnt);
			array_cnt = 0;
			break;
		case 'F':
			len = 1;
			str = get_type_value_str ("float", array_cnt);
			array_cnt = 0;
			break;
		case 'B':
			len = 1;
			str = get_type_value_str ("byte", array_cnt);
			array_cnt = 0;
			break;
		case 'C':
			len = 1;
			str = get_type_value_str ("char", array_cnt);
			array_cnt = 0;
			break;
		case 'Z':
			len = 1;
			str = get_type_value_str ("boolean", array_cnt);
			array_cnt = 0;
			break;
		case 'S':
			len = 1;
			str = get_type_value_str ("short", array_cnt);
			array_cnt = 0;
			break;
		case '[': len = 1; array_cnt++; break;
		case 'L':
			len = r_bin_java_extract_reference_name (arg_str, &str, array_cnt);
			array_cnt = 0;
			break;
		case '(': len = 1; str = strdup ("("); break;
		case ')': len = 1; str = strdup (")"); break;
		default:
			return 0;
		}
		if (len < 1) {
			break;
		}
		consumed += len;
		arg_str += len;
		if (str) {
			*output = str;
			break;
		}
	}
	return consumed;
}

Project: radare2
File: class.c

R_API RBinJavaField *r_bin_java_read_next_field(RBinJavaObj *bin, const ut64 offset, const ut8 *buffer, const ut64 len) {
	RBinJavaAttrInfo *attr;
	ut32 i, idx;
	ut8 buf[8];
	RBinJavaCPTypeObj *item = NULL;
	const ut8 *f_buf = buffer + offset;
	ut64 adv = 0;
	RBinJavaField *field;
	if (bin == NULL) {
		return NULL;
	}
	if (offset + 8 >= len) {
		return NULL;
	}
	field = (RBinJavaField *) R_NEW0 (RBinJavaField);
	if (field == NULL) {
		eprintf ("Unable to allocate memory for field information\n");
		return NULL;
	}
	field->metas = (RBinJavaMetaInfo *) R_NEW0 (RBinJavaMetaInfo);
	if (field->metas == NULL) {
		eprintf ("Unable to allocate memory for meta information\n");
		free (field);
		return NULL;
	}
	memcpy (buf, f_buf, 8);
	field->file_offset = offset;
	field->flags = R_BIN_JAVA_USHORT (buf, 0);
	field->flags_str = retrieve_field_access_string (field->flags);
	field->name_idx = R_BIN_JAVA_USHORT (buf, 2);
	field->descriptor_idx = R_BIN_JAVA_USHORT (buf, 4);
	field->attr_count = R_BIN_JAVA_USHORT (buf, 6);
	field->attributes = r_list_newf (r_bin_java_attribute_free);
	field->type = R_BIN_JAVA_FIELD_TYPE_FIELD;
	adv += 8;
	field->metas->ord = bin->field_idx;

	idx = field->name_idx;
	item = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	field->name = r_bin_java_get_utf8_from_bin_cp_list (bin, (ut32) (field->name_idx));
	IFDBG eprintf("Field name_idx: %d, which is: ord: %d, name: %s, value: %s\n", idx, item->metas->ord, ((RBinJavaCPTypeMetas *)item->metas->type_info)->name, field->name);
	if (field->name == NULL) {
		field->name = (char *) malloc (21);
		snprintf ((char *) field->name, 20, "sym.field_%08x", field->metas->ord);
		IFDBG eprintf("r_bin_java_read_next_field: Unable to find the name for 0x%02x index.\n", field->name_idx);
	}
	idx = field->descriptor_idx;
	item = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	field->descriptor = r_bin_java_get_utf8_from_bin_cp_list (bin, (ut32) field->descriptor_idx);
	IFDBG eprintf("Field descriptor_idx: %d, which is: ord: %d, name: %s, value: %s\n", idx, item->metas->ord, ((RBinJavaCPTypeMetas *)item->metas->type_info)->name, field->descriptor);
	if (field->descriptor == NULL) {
		field->descriptor = r_str_dup (NULL, "NULL");
		IFDBG eprintf("r_bin_java_read_next_field: Unable to find the descriptor for 0x%02x index.\n", field->descriptor_idx);
	}
	IFDBG eprintf("Looking for a NameAndType CP with name_idx: %d descriptor_idx: %d\n", field->name_idx, field->descriptor_idx);
	field->field_ref_cp_obj = r_bin_java_find_cp_ref_info_from_name_and_type (bin, field->name_idx, field->descriptor_idx);
	if (field->field_ref_cp_obj) {
		IFDBG eprintf("Found the obj.\n");
		item = r_bin_java_get_item_from_bin_cp_list (bin, field->field_ref_cp_obj->info.cp_field.class_idx);
		IFDBG eprintf("Field class reference value: %d, which is: ord: %d, name: %s\n", field->field_ref_cp_obj->info.cp_field.class_idx, item->metas->ord, ((RBinJavaCPTypeMetas *)item->metas->type_info)->name);
		field->class_name = r_bin_java_get_item_name_from_bin_cp_list (bin, item);
		IFDBG eprintf("Field requesting ref_cp_obj the following which is: ord: %d, name: %s\n", field->field_ref_cp_obj->metas->ord, ((RBinJavaCPTypeMetas *)field->field_ref_cp_obj->metas->type_info)->name);
		IFDBG eprintf("FieldRef class name resolves to: %s\n", field->class_name);
		if (field->class_name == NULL) {
			field->class_name = r_str_dup (NULL, "NULL");
		}
	} else {
		// XXX - default to this class?
		field->field_ref_cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, bin->cf2.this_class);
		field->class_name = r_bin_java_get_item_name_from_bin_cp_list (bin, field->field_ref_cp_obj);
	}
	IFDBG eprintf("Parsing %s(%s)", field->name, field->descriptor);
	if (field->attr_count > 0) {
		field->attr_offset = adv + offset;
		for (i = 0; i < field->attr_count && offset + adv < len; i++) {
			attr = r_bin_java_read_next_attr (bin, offset + adv, buffer, len);
			if (!attr) {
				eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Field Attribute: %d.\n", i);
				return NULL;
			}
			if ((r_bin_java_get_attr_type_by_name (attr->name))->type == R_BIN_JAVA_ATTR_TYPE_CODE_ATTR) {
				// This is necessary for determing the appropriate number of bytes when readin
				// uoffset, ustack, ulocalvar values
				bin->cur_method_code_length = attr->info.code_attr.code_length;
				bin->offset_sz = 2;// (attr->info.code_attr.code_length > 65535) ? 4 : 2;
				bin->ustack_sz = 2;// (attr->info.code_attr.max_stack > 65535) ? 4 : 2;
				bin->ulocalvar_sz = 2;// (attr->info.code_attr.max_locals > 65535) ? 4 : 2;
			}
			r_list_append (field->attributes, attr);
			adv += attr->size;
			if (adv + offset >= len) {
				eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Field Attribute: %d.\n", i);
				return NULL;
			}
		}
	}
	field->size = adv;
	return field;
}

Project: radare2
File: class.c

R_API void U(r_bin_java_print_stack_map_append_frame_summary)(RBinJavaStackMapFrame * obj) {
	RListIter *iter, *iter_tmp;
	RList *ptrList;
	RBinJavaVerificationObj *ver_obj;
	Eprintf ("Stack Map Frame Information\n");
	Eprintf ("  Tag Value = 0x%02x Name: %s\n", obj->tag, ((RBinJavaStackMapFrameMetas *) obj->metas->type_info)->name);
	Eprintf ("  Offset: 0x%08"PFMT64x "\n", obj->file_offset);
	Eprintf ("  Local Variable Count = 0x%04x\n", obj->number_of_locals);
	Eprintf ("  Local Variables:\n");
	ptrList = obj->local_items;
	r_list_foreach_safe (ptrList, iter, iter_tmp, ver_obj) {
		r_bin_java_print_verification_info_summary (ver_obj);
	}
	Eprintf ("  Stack Items Count = 0x%04x\n", obj->number_of_stack_items);
	Eprintf ("  Stack Items:\n");
	ptrList = obj->stack_items;
	r_list_foreach_safe (ptrList, iter, iter_tmp, ver_obj) {
		r_bin_java_print_verification_info_summary (ver_obj);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_local_variable_type_attr_summary(RBinJavaLocalVariableTypeAttribute *lvattr) {
	if (!lvattr) {
		eprintf ("Attempting to print an invalid RBinJavaLocalVariableTypeAttribute *.\n");
		return;
	}
	eprintf ("   Local Variable Type Attribute offset: 0x%08"PFMT64x "\n", lvattr->file_offset);
	eprintf ("   Local Variable Type Attribute start_pc: %d\n", lvattr->start_pc);
	eprintf ("   Local Variable Type Attribute Length: %d\n", lvattr->length);
	eprintf ("   Local Variable Type Attribute name_idx: %d\n", lvattr->name_idx);
	eprintf ("   Local Variable Type Attribute name: %s\n", lvattr->name);
	eprintf ("   Local Variable Type Attribute signature_idx: %d\n", lvattr->signature_idx);
	eprintf ("   Local Variable Type Attribute signature: %s\n", lvattr->signature);
	eprintf ("   Local Variable Type Attribute index: %d\n", lvattr->index);
}

Project: radare2
File: class.c

R_API void r_bin_java_external_printf(PrintfCallback cb) {
	Eprintf = cb ? cb : (PrintfCallback) printf;
}

Project: radare2
File: class.c

R_API void r_bin_java_local_variable_table_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		r_list_free (attr->info.local_variable_table_attr.local_variable_table);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_bootstrap_method_argument_summary(RBinJavaBootStrapArgument *bsm_arg) {
	if (bsm_arg == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaBootStrapArgument *.\n");
		return;
	}
	eprintf ("Bootstrap Method Argument Information:\n");
	eprintf ("	Offset: 0x%08"PFMT64x"", bsm_arg->file_offset);
	eprintf ("	Name_And_Type Index = (0x%02x)\n", bsm_arg->argument_info_idx);
	if (bsm_arg->argument_info_cp_obj) {
		eprintf ("	Bootstrap Method Argument Type and Name Info:\n");
		((RBinJavaCPTypeMetas *) bsm_arg->argument_info_cp_obj)->allocs->print_summary (bsm_arg->argument_info_cp_obj);
	} else {
		eprintf ("	Bootstrap Method Argument Type and Name Info: INVALID\n");
	}
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_utf8_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *utf8_str = r_hex_bin2strdup (obj->info.cp_utf8.bytes, obj->info.cp_utf8.length);
	char *value = malloc (size + strlen (utf8_str));
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%s",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			obj->info.cp_utf8.length,
			utf8_str);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size + strlen (utf8_str));
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%s",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					obj->info.cp_utf8.length,
					utf8_str);
			}
		}
	}
	free (utf8_str);
	return value;
}

Project: radare2
File: class.c

R_API RBinSymbol *r_bin_java_create_new_symbol_from_ref(RBinJavaCPTypeObj *obj, ut64 baddr) {
	RBinSymbol *sym = R_NEW0 (RBinSymbol);
	if (!sym) {
		return NULL;
	}
	char *class_name, *name, *type_name;
	if (obj == NULL || (obj->tag != R_BIN_JAVA_CP_METHODREF &&
	obj->tag != R_BIN_JAVA_CP_INTERFACEMETHOD_REF &&
	obj->tag != R_BIN_JAVA_CP_FIELDREF)) {
		free (sym);
		sym = NULL;
		return sym;
	}
	if (sym) {
		class_name = r_bin_java_get_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN,
			obj->info.cp_method.class_idx);
		name = r_bin_java_get_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN,
			obj->info.cp_method.name_and_type_idx);
		type_name = r_bin_java_get_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN,
			obj->info.cp_method.name_and_type_idx);
		if (name) {
			sym->name = name;
			name = NULL;
		}
		if (type_name) {
			sym->type = r_str_const (type_name);
			R_FREE (type_name);
		}
		if (class_name) {
			sym->classname = strdup (class_name);
		}
		sym->paddr = obj->file_offset + baddr;
		sym->vaddr = obj->file_offset + baddr;
		sym->ordinal = obj->metas->ord;
		sym->size = 0;
	}
	return sym;
}

Project: radare2
File: class.c

R_API char r_bin_java_resolve_cp_idx_tag(RBinJavaObj *BIN_OBJ, int idx) {
	RBinJavaCPTypeObj *item = NULL;
	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
		// r_bin_java_new_bin(BIN_OBJ);
		return R_BIN_JAVA_CP_UNKNOWN;
	}
	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
	if (item) {
		return item->tag;
	}
	return R_BIN_JAVA_CP_UNKNOWN;
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_classref_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			obj->info.cp_class.name_idx);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					obj->info.cp_class.name_idx);
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API RBinField *r_bin_java_create_new_rbinfield_from_field(RBinJavaField *fm_type, ut64 baddr) {
	RBinField *field = r_bin_java_allocate_rbinfield ();
	if (field) {
		field->name = strdup (fm_type->name);
		field->paddr = fm_type->file_offset + baddr;
		field->visibility = fm_type->flags;
	}
	return field;
}

Project: radare2
File: class.c

R_API int U(r_bin_java_utf8_cp_set)(RBinJavaObj * bin, ut16 idx, const ut8 * buffer, ut32 len) {
	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	if (!cp_obj) {
		return false;
	}
	eprintf ("Writing %d byte(s) (%s)\n", len, buffer);
	// r_bin_java_check_reset_cp_obj(cp_obj, R_BIN_JAVA_CP_INTEGER);
	if (cp_obj->tag != R_BIN_JAVA_CP_UTF8) {
		eprintf ("Not supporting the overwrite of CP Objects with one of a different size.\n");
		return false;
	}
	if (cp_obj->info.cp_utf8.length != len) {
		eprintf ("Not supporting the resize, rewriting utf8 string up to %d byte(s).\n", cp_obj->info.cp_utf8.length);
		if (cp_obj->info.cp_utf8.length > len) {
			eprintf ("Remaining %d byte(s) will be filled with \\x00.\n", cp_obj->info.cp_utf8.length - len);
		}
	}
	memcpy (cp_obj->info.cp_utf8.bytes, buffer, cp_obj->info.cp_utf8.length);
	if (cp_obj->info.cp_utf8.length > len) {
		memset (cp_obj->info.cp_utf8.bytes + len, 0, cp_obj->info.cp_utf8.length - len);
	}
	return true;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_exceptions_attr_summary(RBinJavaAttrInfo *attr) {
	ut32 i = 0;
	if (!attr) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Exceptions.\n");
		return;
	}
	Eprintf ("Exceptions Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
	for (i = 0; i < attr->info.exceptions_attr.number_of_exceptions; i++) {
		Eprintf ("  Exceptions Attribute Index[%d]: %d\n", i, attr->info.exceptions_attr.exception_idx_table[i]);
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_utf8_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	size += 1;
	if (obj && R_BIN_JAVA_CP_UTF8 == obj->tag) {
		size += 2;
		size += obj->info.cp_utf8.length;
	}
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_annotation_free(void /*RBinJavaAnnotation*/ *a) {
	RBinJavaAnnotation *annotation = a;
	if (annotation) {
		r_list_free (annotation->element_value_pairs);
		free (annotation);
	}
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_double_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%f",
			obj->metas->ord,
			obj->file_offset,
			((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			r_bin_java_raw_to_double (obj->info.cp_double.bytes.raw, 0));
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%f",
					obj->metas->ord,
					obj->file_offset,
					((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					r_bin_java_raw_to_double (obj->info.cp_double.bytes.raw, 0));
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_get_method_code_attribute(const RBinJavaField *method) {
	/*
	Search through a methods attributes and return the code attr.
	rvalue: RBinJavaAttrInfo* if found otherwise NULL.
	*/
	RBinJavaAttrInfo *res = NULL, *attr = NULL;
	RListIter *iter;
	if (method) {
		r_list_foreach (method->attributes, iter, attr) {
			if (attr && (attr->type == R_BIN_JAVA_ATTR_TYPE_CODE_ATTR)) {
				res = attr;
				break;
			}
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_utf8_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	RBinJavaCPTypeObj *obj;
	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_UTF8, tag, sz, "Utf8");
	if (quick_check > 0) {
		return NULL;
	}
	if ((obj = R_NEW0 (RBinJavaCPTypeObj))) {
		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
		obj->info.cp_utf8.length = R_BIN_JAVA_USHORT (buffer, 1);
		obj->info.cp_utf8.bytes = (ut8 *) malloc (obj->info.cp_utf8.length + 1);
		if (obj->info.cp_utf8.bytes) {
			memset (obj->info.cp_utf8.bytes, 0, obj->info.cp_utf8.length + 1);
			if (obj->info.cp_utf8.length < (sz - 3)) {
				memcpy (obj->info.cp_utf8.bytes, buffer + 3, (sz - 3));
				obj->info.cp_utf8.length = sz - 3;
			} else {
				memcpy (obj->info.cp_utf8.bytes, buffer + 3, obj->info.cp_utf8.length);
			}
			obj->value = obj->info.cp_utf8.bytes;
		} else {
			r_bin_java_obj_free (obj);
			obj = NULL;
		}
	}
	return obj;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_rtip_annotations_attr_summary(RBinJavaAttrInfo *attr) {
	RBinJavaAnnotationsArray *annotation_array = NULL;
	RListIter *iter = NULL, *iter_tmp = NULL;
	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATION_ATTR) {
		eprintf ("Runtime Invisible Parameter Annotations Attribute Information:\n");
		eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
		eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
		eprintf ("  Attribute Length: %d\n", attr->length);
		eprintf ("  Number of Runtime Invisible Parameters: %d\n", attr->info.rtip_annotations_attr.num_parameters);
		r_list_foreach_safe (attr->info.rtip_annotations_attr.parameter_annotations, iter, iter_tmp, annotation_array) {
			r_bin_java_print_annotation_array_summary (annotation_array);
		}
	}
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_classes(RBinJavaObj *bin) {
	RList *classes = r_list_newf (r_bin_java_classes_free);
	RListIter *iter;
	RBinJavaCPTypeObj *cp_obj = NULL;
	RBinJavaCPTypeObj *this_class_cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, bin->cf2.this_class);
	ut32 idx = 0;
	RBinClass *k = R_NEW0 (RBinClass);
	if (!k) {
		r_list_free (classes);
		return NULL;
	}
	k->visibility = bin->cf2.access_flags;
	if (bin->cf2.flags_str) {
		k->visibility_str = strdup (bin->cf2.flags_str);
	}
	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);
	k->index = (idx++);
	r_list_append (classes, k);
	r_list_foreach (bin->cp_list, iter, cp_obj) {
		if (cp_obj && cp_obj->tag == R_BIN_JAVA_CP_CLASS
		&& (this_class_cp_obj != cp_obj && is_class_interface (bin, cp_obj))) {
			k = R_NEW0 (RBinClass);
			if (!k) {
				break;
			}
			k->methods = r_bin_java_enum_class_methods (bin, cp_obj->info.cp_class.name_idx);
			k->fields = r_bin_java_enum_class_fields (bin, cp_obj->info.cp_class.name_idx);
			k->index = idx;
			k->name = r_bin_java_get_item_name_from_bin_cp_list (bin, cp_obj);
			r_list_append (classes, k);
			idx++;
		}
	}
	return classes;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_attr_calc_size(RBinJavaAttrInfo *attr) {
	return attr ? ((RBinJavaAttrMetas *) attr->metas->type_info)->allocs->calc_size (attr) : 0;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_enclosing_methods_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut64 offset = 6;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	if (!attr) {
		return NULL;
	}
	attr->type = R_BIN_JAVA_ATTR_TYPE_ENCLOSING_METHOD_ATTR;
	attr->info.enclosing_method_attr.class_idx = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.enclosing_method_attr.method_idx = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.enclosing_method_attr.class_name = r_bin_java_get_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, attr->info.enclosing_method_attr.class_idx);
	if (attr->info.enclosing_method_attr.class_name == NULL) {
		eprintf ("Could not resolve enclosing class name for the enclosed method.\n");
	}
	attr->info.enclosing_method_attr.method_name = r_bin_java_get_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, attr->info.enclosing_method_attr.method_idx);
	if (attr->info.enclosing_method_attr.class_name == NULL) {
		eprintf ("Could not resolve method descriptor for the enclosed method.\n");
	}
	attr->info.enclosing_method_attr.method_descriptor = r_bin_java_get_desc_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, attr->info.enclosing_method_attr.method_idx);
	if (attr->info.enclosing_method_attr.method_name == NULL) {
		eprintf ("Could not resolve method name for the enclosed method.\n");
	}
	attr->size = offset;
	return attr;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_verification_info_summary(RBinJavaVerificationObj *obj) {
	ut8 tag_value = R_BIN_JAVA_STACKMAP_UNKNOWN;
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaVerificationObj*  .\n");
		return;
	}
	if (obj->tag < R_BIN_JAVA_STACKMAP_UNKNOWN) {
		tag_value = obj->tag;
	}
	Eprintf ("Verification Information\n");
	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
	Eprintf ("  Tag Value = 0x%02x\n", obj->tag);
	Eprintf ("  Name = %s\n", R_BIN_JAVA_VERIFICATION_METAS[tag_value].name);
	if (obj->tag == R_BIN_JAVA_STACKMAP_OBJECT) {
		Eprintf ("  Object Constant Pool Index = 0x%x\n", obj->info.obj_val_cp_idx);
	} else if (obj->tag == R_BIN_JAVA_STACKMAP_UNINIT) {
		Eprintf ("  Uninitialized Object offset in code = 0x%x\n", obj->info.uninit_offset);
	}
}

Project: radare2
File: class.c

R_API ut16 r_bin_java_calculate_field_access_value(const char *access_flags_str) {
	return calculate_access_value (access_flags_str, FIELD_ACCESS_FLAGS);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_bootstrap_methods_attr_calc_size(RBinJavaAttrInfo *attr) {
	RListIter *iter, *iter_tmp;
	RBinJavaBootStrapMethod *bsm = NULL;
	ut64 size = 0;
	if (attr) {
		size += 6;
		// attr->info.bootstrap_methods_attr.num_bootstrap_methods = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		r_list_foreach_safe (attr->info.bootstrap_methods_attr.bootstrap_methods, iter, iter_tmp, bsm) {
			if (bsm) {
				size += r_bin_java_bootstrap_method_calc_size (bsm);
			} else {
				// TODO eprintf Failed to read the %d boot strap method.
			}
		}
	}
	return size;
}

Project: radare2
File: class.c

R_API RBinJavaBootStrapArgument *r_bin_java_bootstrap_method_argument_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaBootStrapArgument *bsm_arg = NULL;
	ut64 offset = 0;
	bsm_arg = (RBinJavaBootStrapArgument *) malloc (sizeof (RBinJavaBootStrapArgument));
	if (bsm_arg == NULL) {
		// TODO eprintf failed to allocate bytes for bootstrap_method.
		return bsm_arg;
	}
	memset (bsm_arg, 0, sizeof (RBinJavaBootStrapArgument));
	bsm_arg->file_offset = buf_offset;
	bsm_arg->argument_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	bsm_arg->argument_info_cp_obj = r_bin_java_clone_cp_idx (R_BIN_JAVA_GLOBAL_BIN, bsm_arg->argument_info_idx);
	bsm_arg->size = offset;
	return bsm_arg;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_field_num_name(RBinJavaObj *bin_obj) {
	ut32 i = 0;
	RBinJavaField *fm_type;
	RListIter *iter = NULL;
	RList *res = r_list_newf (free);
	r_list_foreach (bin_obj->fields_list, iter, fm_type) {
		ut32 len = strlen (fm_type->name) + 30;
		char *str = malloc (len);
		if (!str) {
			r_list_free (res);
			return NULL;
		}
		snprintf (str, len, "%d %s", i, fm_type->name);
		++i;
		r_list_append (res, str);
	}
	return res;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_methodhandle_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	size += 1;
	// obj->info.cp_method_handle.reference_index =  R_BIN_JAVA_USHORT (buffer, 2);
	size += 2;
	return size;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_parse_interfaces(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
	int i = 0;
	ut64 adv = 0;
	RBinJavaInterfaceInfo *interfaces_obj;
	const ut8 *if_buf = buf + offset;
	bin->cp_offset = offset;
	bin->interfaces_offset = offset;
	r_list_free (bin->interfaces_list);
	bin->interfaces_list = r_list_newf (r_bin_java_interface_free);
	if (offset + 2 > len) {
		bin->interfaces_size = 0;
		return 0;
	}
	bin->interfaces_count = R_BIN_JAVA_USHORT (if_buf, 0);
	adv += 2;
	IFDBG eprintf("Interfaces count: %d\n", bin->interfaces_count);
	if (bin->interfaces_count > 0) {
		for (i = 0; i < bin->interfaces_count; i++) {
			interfaces_obj = r_bin_java_read_next_interface_item (bin, offset + adv, buf, len);
			if (interfaces_obj) {
				r_list_append (bin->interfaces_list, interfaces_obj);
				adv += interfaces_obj->size;
				if (offset + adv > len) {
					eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Interface: %d.\n", i);
					break;
				}
			} else {
				break;
			}
		}
	}
	bin->interfaces_size = adv;
	return adv;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_get_main(RBinJavaObj *bin) {
	if (bin->main_code_attr) {
		return bin->main_code_attr->info.code_attr.code_offset + bin->loadaddr;
	}
	return 0;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_inner_class_attr_calc_size(RBinJavaClassesAttribute *icattr) {
	ut64 size = 0;
	if (icattr) {
		// icattr->inner_class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// icattr->outer_class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// icattr->inner_name_idx = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// icattr->inner_class_access_flags = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
	}
	return size;
}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_get_8bytes(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len) {
	ut8 *buffer = malloc (10);
	if (!buffer) {
		return NULL;
	}
	ut64 val = 0;
	if (len < 8) {
		*out_sz = 0;
		free (buffer);
		return NULL;
	}
	buffer[0] = tag;
	val = r_bin_java_raw_to_long (buf, 0);
	memcpy (buffer + 1, (const char *) &val, 8);
	*out_sz = 9;
	return buffer;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_integer_cp_summary(RBinJavaCPTypeObj *obj) {
	ut8 *b = NULL;
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Integer.\n");
		return;
	}
	b = obj->info.cp_integer.bytes.raw;
	eprintf ("Integer ConstantPool Type (%d) ", obj->metas->ord);
	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
	eprintf ("	bytes = %02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
	eprintf ("	integer = %d\n", R_BIN_JAVA_UINT (obj->info.cp_integer.bytes.raw, 0));
}

Project: radare2
File: class.c

R_API RList *retrieve_all_field_access_string_and_value() {
	return retrieve_all_access_string_and_value (FIELD_ACCESS_FLAGS);
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_sections(RBinJavaObj *bin) {
	RBinSection *section = NULL;
	RList *sections = r_list_newf (free);
	ut64 baddr = bin->loadaddr;
	RBinJavaField *fm_type;
	RListIter *iter = NULL;
	if (bin->cp_count > 0) {
		section = R_NEW0 (RBinSection);
		if (section) {
			strcpy (section->name, "constant_pool");
			section->size = bin->cp_size;
			section->paddr = bin->cp_offset + baddr;
			section->srwx = R_BIN_SCN_READABLE;
			section->add = true;
			r_list_append (sections, section);
		}
		section = NULL;
	}
	if (bin->fields_count > 0) {
		section = R_NEW0 (RBinSection);
		if (section) {
			strcpy (section->name, "fields");
			section->size = bin->fields_size;
			section->paddr = bin->fields_offset + baddr;
			section->srwx = R_BIN_SCN_READABLE;
			section->add = true;
			r_list_append (sections, section);
			section = NULL;
			r_list_foreach (bin->fields_list, iter, fm_type) {
				if (fm_type->attr_offset == 0) {
					continue;
				}
				section = R_NEW0 (RBinSection);
				if (section) {
					snprintf (section->name, R_BIN_SIZEOF_STRINGS, "attrs.%s", fm_type->name);
					section->size = fm_type->size - (fm_type->file_offset - fm_type->attr_offset);
					section->paddr = fm_type->attr_offset + baddr;
					section->srwx = R_BIN_SCN_READABLE;
					section->add = true;
					r_list_append (sections, section);
				}
			}
		}
	}
	if (bin->methods_count > 0) {
		section = R_NEW0 (RBinSection);
		if (section) {
			strcpy (section->name, "methods");
			section->size = bin->methods_size;
			section->paddr = bin->methods_offset + baddr;
			section->srwx = R_BIN_SCN_READABLE | R_BIN_SCN_EXECUTABLE;
			section->add = true;
			r_list_append (sections, section);
			section = NULL;
			r_list_foreach (bin->methods_list, iter, fm_type) {
				if (fm_type->attr_offset == 0) {
					continue;
				}
				section = R_NEW0 (RBinSection);
				if (section) {
					snprintf (section->name, R_BIN_SIZEOF_STRINGS, "attrs.%s", fm_type->name);
					section->size = fm_type->size - (fm_type->file_offset - fm_type->attr_offset);
					section->paddr = fm_type->attr_offset + baddr;
					section->srwx = R_BIN_SCN_READABLE;
					section->add = true;
					r_list_append (sections, section);
				}
			}
		}
	}
	if (bin->interfaces_count > 0) {
		section = R_NEW0 (RBinSection);
		if (section) {
			strcpy (section->name, "interfaces");
			section->size = bin->interfaces_size;
			section->paddr = bin->interfaces_offset + baddr;
			section->srwx = R_BIN_SCN_READABLE;
			section->add = true;
			r_list_append (sections, section);
		}
		section = NULL;
	}
	if (bin->attrs_count > 0) {
		section = R_NEW0 (RBinSection);
		if (section) {
			strcpy (section->name, "attributes");
			section->size = bin->attrs_size;
			section->paddr = bin->attrs_offset + baddr;
			section->srwx = R_BIN_SCN_READABLE;
			section->add = true;
			r_list_append (sections, section);
		}
		section = NULL;
	}
	return sections;
}

Project: radare2
File: class.c

R_API void U(r_bin_java_free_const_value)(ConstJavaValue * cp_value) {
	char first_char = cp_value && cp_value->type ? *cp_value->type : 0,
	second_char = cp_value && cp_value->type ? *(cp_value->type + 1) : 0;
	switch (first_char) {
	case 'r':
		if (cp_value && cp_value->value._ref) {
			free (cp_value->value._ref->class_name);
			free (cp_value->value._ref->name);
			free (cp_value->value._ref->desc);
		}
		break;
	case 's':
		if (second_char == 't' && cp_value->value._str) {
			free (cp_value->value._str->str);
		}
		break;
	}
	free (cp_value);
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_strings(RBinJavaObj *bin) {
	RList *strings = r_list_newf (free);
	RBinString *str = NULL;
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaCPTypeObj *cp_obj = NULL;
	r_list_foreach_safe (bin->cp_list, iter, iter_tmp, cp_obj) {
		if (cp_obj && cp_obj->tag == R_BIN_JAVA_CP_UTF8) {
			str = (RBinString *) R_NEW0 (RBinString);
			if (str) {
				str->paddr = cp_obj->file_offset + bin->loadaddr;
				str->ordinal = cp_obj->metas->ord;
				str->size = cp_obj->info.cp_utf8.length + 3;
				str->length = cp_obj->info.cp_utf8.length;
				if (str->size > 0) {
					str->string = r_str_ndup ((const char *)
						cp_obj->info.cp_utf8.bytes,
						R_BIN_JAVA_MAXSTR);
				}
				r_list_append (strings, (void *) str);
			}
		}
	}
	return strings;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_rtip_annotations_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 0;
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaAnnotationsArray *annotation_array;
	if (attr == NULL) {
		// TODO eprintf allocation fail
		return size;
	}
	// attr->info.rtip_annotations_attr.num_parameters = buffer[offset];
	size += (6 + 1);
	r_list_foreach_safe (attr->info.rtip_annotations_attr.parameter_annotations, iter, iter_tmp, annotation_array) {
		if (annotation_array) {
			size += r_bin_java_annotation_array_calc_size (annotation_array);
		}
	}
	return size;
}

Project: radare2
File: class.c

R_API int U(r_bin_java_integer_cp_set)(RBinJavaObj * bin, ut16 idx, ut32 val) {
	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	if (!cp_obj) {
		return false;
	}
	ut8 bytes[4] = {
		0
	};
	if (cp_obj->tag != R_BIN_JAVA_CP_INTEGER && cp_obj->tag != R_BIN_JAVA_CP_FLOAT) {
		eprintf ("Not supporting the overwrite of CP Objects with one of a different size.\n");
		return false;
	}
	r_bin_java_check_reset_cp_obj (cp_obj, R_BIN_JAVA_CP_INTEGER);
	cp_obj->tag = R_BIN_JAVA_CP_INTEGER;
	memcpy (bytes, (const char *) &val, 4);
	val = R_BIN_JAVA_UINT (bytes, 0);
	memcpy (&cp_obj->info.cp_integer.bytes.raw, (const char *) &val, 4);
	return true;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_enum_class_methods(RBinJavaObj *bin, ut16 class_idx) {
	RList *methods = r_list_newf (free);
	RListIter *iter;
	RBinJavaField *field;
	r_list_foreach (bin->methods_list, iter, field) {
		if (field->field_ref_cp_obj && 0) {
			if ((field && field->field_ref_cp_obj->metas->ord == class_idx)) {
				RBinSymbol *sym = r_bin_java_create_new_symbol_from_ref (
						field->field_ref_cp_obj, bin->loadaddr);
				if (sym) {
					r_list_append (methods, sym);
				}
			}
		} else {
			RBinSymbol *sym = R_NEW0 (RBinSymbol);
			sym->name = strdup (field->name);
			// func defintion
			// sym->paddr = field->file_offset + bin->loadaddr;
			// code implementation
			sym->paddr = r_bin_java_get_method_code_offset (field);
			sym->vaddr = sym->paddr; // + bin->loadaddr;
			r_list_append (methods, sym);
		}
	}
	return methods;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_double_cp_summary(RBinJavaCPTypeObj *obj) {
	ut8 *b = NULL;
	if (!obj) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Double.\n");
		return;
	}
	b = obj->info.cp_double.bytes.raw;
	Eprintf ("Double ConstantPool Type (%d) ", obj->metas->ord);
	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
	Eprintf ("  High-Bytes = %02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
	Eprintf ("  Low-Bytes = %02x %02x %02x %02x\n", b[4], b[5], b[6], b[7]);
	Eprintf ("  Double = %f\n", r_bin_java_raw_to_double (obj->info.cp_double.bytes.raw, 0));
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_read_next_constant_pool_item(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, ut64 len) {
	RBinJavaCPTypeMetas *java_constant_info = NULL;
	ut8 tag = 0;
	ut64 buf_sz = 0;
	ut8 *cp_buf = NULL;
	ut32 str_len = 0;
	RBinJavaCPTypeObj *java_obj = NULL;
	tag = buf[offset];
	if (tag > R_BIN_JAVA_CP_METAS_SZ) {
		eprintf ("Invalid tag '%d' at offset 0x%08"PFMT64x "\n", tag, (ut64) offset);
		return NULL;
#if 0
		java_obj = r_bin_java_unknown_cp_new (bin, &tag, 1);
		if (java_obj != NULL && java_obj->metas != NULL) {
			java_obj->file_offset = offset;
			java_obj->loadaddr = bin->loadaddr;
		}
		return NULL; // early error to avoid future overflows
		// return java_obj;
#endif
	}
	java_constant_info = &R_BIN_JAVA_CP_METAS[tag];
	if (java_constant_info->tag == 0 || java_constant_info->tag == 2) {
		return java_obj;
	}
	buf_sz += java_constant_info->len;
	if (java_constant_info->tag == 1) {
		if (offset + 32 < len) {
			str_len = R_BIN_JAVA_USHORT (buf, offset + 1);
			buf_sz += str_len;
		} else {
			return NULL;
		}
	}
	cp_buf = calloc (buf_sz, 1);
	if (!cp_buf) {
		return java_obj;
	}
	if (offset + buf_sz < len) {
		memcpy (cp_buf, (ut8 *) buf + offset, buf_sz);
		IFDBG eprintf("Parsed the tag '%d':%s and create object from offset 0x%08"PFMT64x ".\n", tag, R_BIN_JAVA_CP_METAS[tag].name, offset);
		java_obj = (*java_constant_info->allocs->new_obj)(bin, cp_buf, buf_sz);
		if (java_obj != NULL && java_obj->metas != NULL) {
			java_obj->file_offset = offset;
			// IFDBG eprintf ("java_obj->file_offset = 0x%08"PFMT64x".\n",java_obj->file_offset);
		} else if (!java_obj) {
			eprintf ("Unable to parse the tag '%d' and create valid object.\n", tag);
		} else if (!java_obj->metas) {
			eprintf ("Unable to parse the tag '%d' and create valid object.\n", tag);
		} else {
			eprintf ("Failed to set the java_obj->metas-file_offset for '%d' offset is(0x%08"PFMT64x ").\n", tag, offset);
		}
	}
	free (cp_buf);
	return java_obj;
}

Project: radare2
File: class.c

R_API int r_bin_java_extract_reference_name(const char *input_str, char **ref_str, ut8 array_cnt) {
	char *new_str = NULL;
	ut32 str_len = array_cnt ? (array_cnt + 1) * 2 : 0;
	const char *str_pos = input_str;
	int consumed = 0, len = 0;
	if (!str_pos || *str_pos != 'L' || !*str_pos) {
		return -1;
	}
	consumed++;
	str_pos++;
	while (*str_pos && *str_pos != ';') {
		str_pos++;
		len++;
		consumed++;
	}
	str_pos = input_str + 1;
	free (*ref_str);
	str_len += len;
	*ref_str = malloc (str_len + 1);
	new_str = *ref_str;
	memcpy (new_str, input_str + 1, str_len);
	new_str[str_len] = 0;
	while (*new_str) {
		if (*new_str == '/') {
			*new_str = '.';
		}
		new_str++;
	}
	return len + 2;
}

Project: radare2
File: class.c

R_API char *U(r_bin_java_get_fcn_name_from_bin)(RBinJavaObj * bin_obj, ut64 addr) {
	RBinJavaField *fm_type = r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr);
	return fm_type && fm_type->name ? strdup (fm_type->name) : NULL;
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_null_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s",
					obj->metas->ord, obj->file_offset,
					((RBinJavaCPTypeMetas *) obj->metas->type_info)->name);
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_get_class_entrypoint(RBinJavaObj *bin) {
	if (bin->cf2.this_class_entrypoint_code_attr) {
		return bin->cf2.this_class_entrypoint_code_attr->info.code_attr.code_offset;
	}
	return 0;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_find_cp_name_and_type_info(RBinJavaObj *bin, ut16 name_idx, ut16 descriptor_idx) {
	RListIter *iter, *iter_tmp;
	RBinJavaCPTypeObj *res = NULL, *obj = NULL;
	IFDBG eprintf("Looking for name_idx: %d and descriptor_idx: %d\n", name_idx, descriptor_idx);
	r_list_foreach_safe (bin->cp_list, iter, iter_tmp, obj) {
		if (obj && obj->tag == R_BIN_JAVA_CP_NAMEANDTYPE) {
			IFDBG eprintf("RBinJavaCPTypeNameAndType has name_idx: %d and descriptor_idx: %d\n",
			obj->info.cp_name_and_type.name_idx, obj->info.cp_name_and_type.descriptor_idx);
			if (obj->info.cp_name_and_type.name_idx == name_idx &&
			obj->info.cp_name_and_type.descriptor_idx == descriptor_idx) {
				res = obj;
				break;
			}
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_double_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	// tag
	size += 1;
	// obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
	size += 8;
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_annotation_default_attr_summary(RBinJavaAttrInfo *attr) {
	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_ANNOTATION_DEFAULT_ATTR) {
		eprintf ("Annotation Default Attribute Information:\n");
		eprintf ("   Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
		eprintf ("   Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
		eprintf ("   Attribute Length: %d\n", attr->length);
		r_bin_java_print_element_value_summary ((attr->info.annotation_default_attr.default_value));
	} else {
		// TODO: eprintf attr is invalid
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_inner_classes_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		r_list_free (attr->info.inner_classes_attr.classes);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_string_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			obj->info.cp_string.string_idx);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
					obj->metas->ord, obj->file_offset,
					((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					obj->info.cp_string.string_idx);
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_method_num_name(RBinJavaObj *bin_obj) {
	ut32 i = 0;
	RListIter *iter = NULL;
	RBinJavaField *fm_type;
	RList *res = r_list_newf (free);
	r_list_foreach (bin_obj->methods_list, iter, fm_type) {
		ut32 len = strlen (fm_type->name) + 30;
		char *str = malloc (len);
		snprintf (str, len, "%d %s", i, fm_type->name);
		++i;
		r_list_append (res, str);
	}
	return res;
}

Project: radare2
File: class.c

R_API void U(add_cp_objs_to_sdb)(RBinJavaObj * bin) {
	/*
	Add Constant Pool Serialized Object to an Array
	the key for this info is:
	Key:
	java.<classname>.cp_obj
	Each Value varies by type:
	In general its:
	<ordinal>.<file_offset>.<type_name>.[type specific stuff]
	Example:
	UTF-8:  <ordinal>.<file_offset>.<type_name>.<strlen>.<hexlified(str)>
	Integer: <ordinal>.<file_offset>.<type_name>.<abs(int)>
	Long: <ordinal>.<file_offset>.<type_name>.abs(long)>
	FieldRef/MethodRef: <ordinal>.<file_offset>.<type_name>.<class_idx>.<name_and_type_idx>
	*/
	ut32 idx = 0, class_name_inheap = 1;
	RBinJavaCPTypeObj *cp_obj = NULL;
	char *key = NULL,
	*value = NULL;
	char str_cnt[40];
	char *class_name = r_bin_java_get_this_class_name (bin);
	ut32 key_buf_size = 0;
	if (class_name == NULL) {
		class_name = "unknown";
		class_name_inheap = 0;
	}
	// 4 - format, 8 number, 1 null byte, 7 "unknown"
	key_buf_size = strlen (class_name) + 4 + 8 + 1;
	key = malloc (key_buf_size);
	if (key == NULL) {
		if (class_name_inheap) {
			free (class_name);
		}
		return;
	}
	snprintf (key, key_buf_size - 1, "%s.cp_count", class_name);
	key[key_buf_size - 1] = 0;
	snprintf (str_cnt, 39, "%d", bin->cp_count);
	str_cnt[39] = 0;
	sdb_set (bin->kv, key, value, 0);
	// sdb_alist(bin->kv, key);
	for (idx = 0; idx < bin->cp_count; idx++) {
		snprintf (key, key_buf_size - 1, "%s.cp.%d", class_name, idx);
		key[key_buf_size - 1] = 0;
		cp_obj = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (bin, idx);
		IFDBG eprintf("Adding %s to the sdb.\n", key);
		if (cp_obj) {
			value = ((RBinJavaCPTypeMetas *)
			cp_obj->metas->type_info)->
			allocs->stringify_obj (cp_obj);
			sdb_set (bin->kv, key, value, 0);
			free (value);
		}
	}
	if (class_name_inheap) {
		free (class_name);
	}
	free (key);
}

Project: radare2
File: class.c

R_API void r_bin_java_code_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		// XXX - Intentional memory leak here.  When one of the
		// Code attributes is parsed, the code (the r_bin_java)
		// is not properly parsing the class file
		r_bin_java_stack_frame_free (attr->info.code_attr.implicit_frame);
		r_list_free (attr->info.code_attr.attributes);
		free (attr->info.code_attr.code);
		r_list_free (attr->info.code_attr.exception_table);
		free (attr->name);
		free (attr->metas);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_element_pair_calc_size(RBinJavaElementValuePair *ev_pair) {
	ut64 sz = 0;
	if (ev_pair == NULL) {
		return sz;
	}
	// ev_pair->element_name_idx = r_bin_java_read_short(bin, bin->b->cur);
	sz += 2;
	// ev_pair->value = r_bin_java_element_value_new (bin, offset+2);
	if (ev_pair->value) {
		sz += r_bin_java_element_value_calc_size (ev_pair->value);
	}
	return sz;
}

Project: radare2
File: class.c

R_API ut64 rbin_java_verification_info_calc_size(RBinJavaVerificationObj *se) {
	ut64 sz = 1;
	if (!se) {
		return 0;
	}
	// r_buf_read_at (bin->b, offset, (ut8*)(&se->tag), 1)
	switch (se->tag) {
	case R_BIN_JAVA_STACKMAP_OBJECT:
		// r_buf_read_at (bin->b, offset+1, (ut8*)buf, 2)
		sz += 2;
		break;
	case R_BIN_JAVA_STACKMAP_UNINIT:
		// r_buf_read_at (bin->b, offset+1, (ut8*)buf, 2)
		sz += 2;
		break;
	}
	return sz;
}

Project: radare2
File: class.c

R_API char *r_bin_java_resolve_without_space(RBinJavaObj *obj, int idx) {
	return r_bin_java_resolve (obj, idx, 0);
}

Project: radare2
File: class.c

R_API RBinSymbol *r_bin_java_create_new_symbol_from_field(RBinJavaField *fm_type, ut64 baddr) {
	RBinSymbol *sym = R_NEW0 (RBinSymbol);
	if (fm_type == NULL || fm_type->field_ref_cp_obj == NULL || fm_type->field_ref_cp_obj == &R_BIN_JAVA_NULL_TYPE) {
		free (sym);
		sym = NULL;
	}
	if (sym) {
		sym->name = strdup (fm_type->name);
		// strncpy (sym->type, fm_type->descriptor, R_BIN_SIZEOF_STRINGS);
		if (fm_type->type == R_BIN_JAVA_FIELD_TYPE_METHOD) {
			sym->type = r_str_const (R_BIN_TYPE_FUNC_STR);
			sym->paddr = r_bin_java_get_method_code_offset (fm_type);
			sym->vaddr = r_bin_java_get_method_code_offset (fm_type) + baddr;
			sym->size = r_bin_java_get_method_code_size (fm_type);
		} else {
			sym->type = r_str_const ("FIELD");
			sym->paddr = fm_type->file_offset;// r_bin_java_get_method_code_offset (fm_type);
			sym->vaddr = fm_type->file_offset + baddr;
			sym->size = fm_type->size;
		}
		if (r_bin_java_is_fm_type_protected (fm_type)) {
			sym->bind = r_str_const (R_BIN_BIND_LOCAL_STR);
		} else if (r_bin_java_is_fm_type_private (fm_type)) {
			sym->bind = r_str_const (R_BIN_BIND_LOCAL_STR);
		} else if (r_bin_java_is_fm_type_protected (fm_type)) {
			sym->bind = r_str_const (R_BIN_BIND_GLOBAL_STR);
		}
		sym->forwarder = r_str_const ("NONE");
		if (fm_type->class_name) {
			sym->classname = strdup (fm_type->class_name);
		} else {
			sym->classname = strdup ("UNKNOWN"); // dupped names?
		}
		sym->ordinal = fm_type->metas->ord;
		sym->visibility = fm_type->flags;
		if (fm_type->flags_str) {
			sym->visibility_str = strdup (fm_type->flags_str);
		}
	}
	return sym;
}

Project: radare2
File: class.c

R_API RBinJavaInterfaceInfo *r_bin_java_read_next_interface_item(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
	ut8 idx[2] = {
		0
	};
	RBinJavaInterfaceInfo *ifobj;
	const ut8 *if_buf = buf + offset;
	if (offset + 2 >= len) {
		return NULL;
	}
	memcpy (&idx, if_buf, 2);
	ifobj = r_bin_java_interface_new (bin, if_buf, len - offset);
	if (ifobj) {
		ifobj->file_offset = offset;
	}
	return ifobj;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_signature_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut64 offset = 6;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	if (!attr) {
		return NULL;
	}
	attr->type = R_BIN_JAVA_ATTR_TYPE_SIGNATURE_ATTR;
	// attr->info.source_file_attr.sourcefile_idx = R_BIN_JAVA_USHORT (buffer, offset);
	// offset += 2;
	attr->info.signature_attr.signature_idx = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.signature_attr.signature = r_bin_java_get_utf8_from_bin_cp_list (
		R_BIN_JAVA_GLOBAL_BIN, attr->info.signature_attr.signature_idx);
	if (!attr->info.signature_attr.signature) {
		eprintf ("r_bin_java_signature_attr_new: Unable to resolve the "
			"Signature UTF8 String Index: 0x%02x\n", attr->info.signature_attr.signature_idx);
	}
	attr->size = offset;
	// IFDBG r_bin_java_print_source_code_file_attr_summary(attr);
	return attr;
}

Project: radare2
File: class.c

R_API RBinJavaStackMapFrame *r_bin_java_default_stack_frame() {
	RBinJavaStackMapFrame *sf = R_NEW0 (RBinJavaStackMapFrame);
	if (!sf) {
		return NULL;
	}
	sf->metas = R_NEW0 (RBinJavaMetaInfo);
	if (!sf->metas) {
		free (sf);
		return NULL;
	}
	sf->metas->type_info = (void *) &R_BIN_JAVA_STACK_MAP_FRAME_METAS[R_BIN_JAVA_STACK_FRAME_IMPLICIT];
	sf->type = ((RBinJavaStackMapFrameMetas *) sf->metas->type_info)->type;
	sf->local_items = r_list_newf (r_bin_java_verification_info_free);
	sf->stack_items = r_list_newf (r_bin_java_verification_info_free);
	sf->number_of_stack_items = 0;
	sf->number_of_locals = 0;
	return sf;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_entrypoints(RBinJavaObj *bin) {
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaField *fm_type;
	RList *ret = r_list_newf (free);
	if (!ret) {
		return NULL;
	}
	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
		if (!strcmp (fm_type->name, "main")
		|| !strcmp (fm_type->name, "<init>")
		|| !strcmp (fm_type->name, "<clinit>")
		|| strstr (fm_type->flags_str, "static")) {
			RBinAddr *addr = R_NEW0 (RBinAddr);
			if (addr) {
				addr->vaddr = addr->paddr = \
					r_bin_java_get_method_code_offset (fm_type) + bin->loadaddr;
				addr->haddr = fm_type->file_offset;
				r_list_append (ret, addr);
			}
		}
	}
	return ret;
}

Project: radare2
File: class.c

R_API ConstJavaValue *U(r_bin_java_resolve_to_const_value)(RBinJavaObj * BIN_OBJ, int idx) {
	// TODO XXX FIXME add a size parameter to the str when it is passed in
	RBinJavaCPTypeObj *item = NULL, *item2 = NULL;
	ConstJavaValue *result = R_NEW0 (ConstJavaValue);
	if (!result) {
		return NULL;
	}
	char *class_str = NULL,
	*name_str = NULL,
	*desc_str = NULL,
	*string_str = NULL,
	*empty = "",
	*cp_name = NULL;
	result->type = "unknown";
	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
		// r_bin_java_new_bin(BIN_OBJ);
		return result;
	}
	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
	if (item) {
		cp_name = ((RBinJavaCPTypeMetas *) item->metas->type_info)->name;
		IFDBG eprintf("java_resolve Resolved: (%d) %s\n", idx, cp_name);
	} else {
		return result;
	}
	cp_name = ((RBinJavaCPTypeMetas *) item->metas->type_info)->name;
	if (strcmp (cp_name, "Class") == 0) {
		item2 = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
		// str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, idx-1);
		class_str = empty;
		class_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
		if (!class_str) {
			class_str = empty;
		}
		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item2);
		if (!name_str) {
			name_str = empty;
		}
		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item2);
		if (!desc_str) {
			desc_str = empty;
		}
		result->value._ref = R_NEW0 (_JavaRef);
		result->type = "ref";
		result->value._ref->class_name = strdup (class_str);
		result->value._ref->name = strdup (name_str);
		result->value._ref->desc = strdup (desc_str);
		if (class_str != empty) {
			free (class_str);
		}
		if (name_str != empty) {
			free (name_str);
		}
		if (desc_str != empty) {
			free (desc_str);
		}
	} else if (strcmp (cp_name, "MethodRef") == 0 ||
	strcmp (cp_name, "FieldRef") == 0 ||
	strcmp (cp_name, "InterfaceMethodRef") == 0) {
		/*
		*  The MethodRef, FieldRef, and InterfaceMethodRef structures
		*/
		class_str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, item->info.cp_method.class_idx);
		if (!class_str) {
			class_str = empty;
		}
		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
		if (!name_str) {
			name_str = empty;
		}
		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
		if (!desc_str) {
			desc_str = empty;
		}
		result->value._ref = R_NEW0 (_JavaRef);
		result->type = "ref";
		result->value._ref->class_name = strdup (class_str);
		result->value._ref->name = strdup (name_str);
		result->value._ref->desc = strdup (desc_str);
		if (class_str != empty) {
			free (class_str);
		}
		if (name_str != empty) {
			free (name_str);
		}
		if (desc_str != empty) {
			free (desc_str);
		}
	} else if (strcmp (cp_name, "String") == 0) {
		ut32 length = r_bin_java_get_utf8_len_from_bin_cp_list (BIN_OBJ, item->info.cp_string.string_idx);
		string_str = r_bin_java_get_utf8_from_bin_cp_list (BIN_OBJ, item->info.cp_string.string_idx);
		IFDBG eprintf("java_resolve String got: (%d) %s\n", item->info.cp_string.string_idx, string_str);
		if (!string_str) {
			string_str = empty;
			length = strlen (empty);
		}
		result->type = "str";
		result->value._str = R_NEW0 (struct  java_const_value_str_t);
		result->value._str->len = length;
		if (length > 0) {
			result->value._str->str = malloc (length);
			memcpy (result->value._str->str, string_str, length);
		} else {
			result->value._str->str = strdup ("");
		}
		if (string_str != empty) {
			free (string_str);
		}
	} else if (strcmp (cp_name, "Utf8") == 0) {
		result->type = "str";
		result->value._str = R_NEW0 (struct java_const_value_str_t);
		result->value._str->str = malloc (item->info.cp_utf8.length);
		result->value._str->len = item->info.cp_utf8.length;
		memcpy (result->value._str->str, item->info.cp_utf8.bytes, item->info.cp_utf8.length);
	} else if (strcmp (cp_name, "Long") == 0) {
		result->type = "long";
		result->value._long = r_bin_java_raw_to_long (item->info.cp_long.bytes.raw, 0);
	} else if (strcmp (cp_name, "Double") == 0) {
		result->type = "double";
		result->value._double = r_bin_java_raw_to_double (item->info.cp_double.bytes.raw, 0);
	} else if (strcmp (cp_name, "Integer") == 0) {
		result->type = "int";
		result->value._int = R_BIN_JAVA_UINT (item->info.cp_integer.bytes.raw, 0);
	} else if (strcmp (cp_name, "Float") == 0) {
		result->type = "float";
		result->value._float = R_BIN_JAVA_FLOAT (item->info.cp_float.bytes.raw, 0);
	} else if (strcmp (cp_name, "NameAndType") == 0) {
		result->value._ref = R_NEW0 (struct java_const_value_ref_t);
		result->type = "ref";
		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
		if (!name_str) {
			name_str = empty;
		}
		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
		if (!desc_str) {
			desc_str = empty;
		}
		result->value._ref->class_name = strdup (empty);
		result->value._ref->name = strdup (name_str);
		result->value._ref->desc = strdup (desc_str);
		if (name_str != empty) {
			free (name_str);
		}
		if (desc_str != empty) {
			free (desc_str);
		}
		result->value._ref->is_method = r_bin_java_does_cp_idx_ref_method (BIN_OBJ, idx);
		result->value._ref->is_field = r_bin_java_does_cp_idx_ref_field (BIN_OBJ, idx);
	}
	return result;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_utf8_from_bin_cp_list(RBinJavaObj *bin, ut64 idx) {
	/*
	Search through the Constant Pool list for the given CP Index.
	If the idx not found by directly going to the list index,
	the list will be walked and then the IDX will be checked.
	rvalue: new char* for caller to free.
	*/
	if (bin == NULL) {
		return NULL;
	}
	return r_bin_java_get_utf8_from_cp_item_list (bin->cp_list, idx);
}

Project: radare2
File: class.c

R_API RList *retrieve_all_method_access_string_and_value() {
	return retrieve_all_access_string_and_value (METHOD_ACCESS_FLAGS);
}

Project: radare2
File: class.c

R_API int U(r_bin_java_get_cp_idx_with_name)(RBinJavaObj * bin_obj, const char *name, ut32 len) {
	RListIter *iter;
	RBinJavaCPTypeObj *obj;
	r_list_foreach (bin_obj->cp_list, iter, obj) {
		if (obj->tag == R_BIN_JAVA_CP_UTF8) {
			if (!strncmp (name, (const char *) obj->info.cp_utf8.bytes, len)) {
				return obj->metas->ord;
			}
		}
	}
	return 0;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_class_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	// ut8 tag = buffer[0];
	size += 1;
	// obj->info.cp_class.name_idx = R_BIN_JAVA_USHORT (buffer, 1);
	size += 2;
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_unknown_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_long_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	// tag
	size += 1;
	// obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
	size += 8;
	return size;
}

Project: radare2
File: class.c

R_API RBinJavaAnnotation *r_bin_java_annotation_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	RBinJavaAnnotation *annotation = NULL;
	RBinJavaElementValuePair *ev_pairs = NULL;
	ut64 offset = 0;
	annotation = R_NEW0 (RBinJavaAnnotation);
	if (!annotation) {
		return NULL;
	}
	// (ut16) read and set annotation_value.type_idx;
	annotation->type_idx = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	// (ut16) read and set annotation_value.num_element_value_pairs;
	annotation->num_element_value_pairs = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	annotation->element_value_pairs = r_list_newf (r_bin_java_element_pair_free);
	// read annotation_value.num_element_value_pairs, and append to annotation_value.element_value_pairs
	for (i = 0; i < annotation->num_element_value_pairs; i++) {
		if (offset > sz) {
			break;
		}
		ev_pairs = r_bin_java_element_pair_new (buffer + offset, sz - offset, buf_offset + offset);
		if (ev_pairs) {
			offset += ev_pairs->size;
			r_list_append (annotation->element_value_pairs, (void *) ev_pairs);
		}
	}
	annotation->size = offset;
	return annotation;
}

Project: radare2
File: class.c

R_API DsoJsonObj *r_bin_java_get_interface_json_definitions(RBinJavaObj *bin) {
	RList *the_list;
	DsoJsonObj *json_list = dso_json_list_new ();
	RListIter *iter = NULL;
	char *new_str;

	if (!bin || !(the_list = r_bin_java_get_interface_names (bin))) {
		return json_list;
	}

	r_list_foreach (the_list, iter, new_str) {
		char *tmp = new_str;
		// eprintf ("Processing string: %s\n", new_str);
		while (*tmp) {
			if (*tmp == '/') {
				*tmp = '.';
			}
			tmp++;
		}
		// eprintf ("adding string: %s\n", new_str);
		dso_json_list_append_str (json_list, new_str);
	}
	r_list_free (the_list);
	return json_list;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_invokedynamic_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	size += 1;
	// obj->info.cp_invoke_dynamic.bootstrap_method_attr_index = R_BIN_JAVA_USHORT (buffer, 1);
	size += 2;
	// obj->info.cp_invoke_dynamic.name_and_type_index = R_BIN_JAVA_USHORT (buffer, 3);
	size += 2;
	return size;
}

Project: radare2
File: class.c

R_API char *retrieve_access_string(ut16 flags, RBinJavaAccessFlags *access_flags) {
	char *outbuffer = NULL, *cur_pos = NULL;
	ut16 i;
	ut16 max_str_len = 0;
	for (i = 0; access_flags[i].str != NULL; i++) {
		if (flags & access_flags[i].value) {
			max_str_len += (strlen (access_flags[i].str) + 1);
			if (max_str_len < strlen (access_flags[i].str)) {
				return NULL;
			}
		}
	}
	max_str_len++;
	outbuffer = (char *) malloc (max_str_len);
	if (outbuffer) {
		memset (outbuffer, 0, max_str_len);
		cur_pos = outbuffer;
		for (i = 0; access_flags[i].str != NULL; i++) {
			if (flags & access_flags[i].value) {
				ut8 len = strlen (access_flags[i].str);
				const char *the_string = access_flags[i].str;
				memcpy (cur_pos, the_string, len);
				memcpy (cur_pos + len, " ", 1);
				cur_pos += len + 1;
			}
		}
		if (cur_pos != outbuffer) {
			*(cur_pos - 1) = 0;
		}
	}
	return outbuffer;
}