Commit message: Fix oobread segfault in java arith8.class ##crash

* Reported by Cen Zhang via huntr.dev
CVE: CVE-2022-0518
CWE: CWE-787
Vulnerability description: Heap-based Buffer Overflow in GitHub repository radareorg/radare2 prior to 5.6.2.

Project: radare2

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) {
		R_FREE (sym);
	}
	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_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 = "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_BIN_BIND_LOCAL_STR;
		} else if (r_bin_java_is_fm_type_private (fm_type)) {
			sym->bind = R_BIN_BIND_LOCAL_STR;
		} else if (r_bin_java_is_fm_type_protected (fm_type)) {
			sym->bind = R_BIN_BIND_GLOBAL_STR;
		}
		sym->forwarder = "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

R_API char *r_bin_java_print_methodref_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_method.class_idx,
			obj->info.cp_method.name_and_type_idx);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				(void)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_method.class_idx,
					obj->info.cp_method.name_and_type_idx);
			}
		}
	}
	return value;
}

Project: radare2

R_API RBinJavaAttrInfo *r_bin_java_code_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaAttrInfo *attr = NULL, *_attr = NULL;
	ut32 k = 0, curpos;
	ut64 offset = 0;
	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
	if (!attr) {
		return NULL;
	}
	if (sz < 16 || sz > buf_offset) {// sz > buf_offset) {
		free (attr);
		return NULL;
	}
	offset += 6;
	attr->type = R_BIN_JAVA_ATTR_TYPE_CODE_ATTR;
	attr->info.code_attr.max_stack = attr->is_attr_in_old_format ? buffer[offset] : R_BIN_JAVA_USHORT (buffer, offset);
	offset += attr->is_attr_in_old_format ? 1 : 2;
	attr->info.code_attr.max_locals = attr->is_attr_in_old_format ? buffer[offset] : R_BIN_JAVA_USHORT (buffer, offset);
	offset += attr->is_attr_in_old_format ? 1 : 2;
	attr->info.code_attr.code_length = attr->is_attr_in_old_format ? R_BIN_JAVA_USHORT(buffer, offset) : R_BIN_JAVA_UINT (buffer, offset);
	offset += attr->is_attr_in_old_format ? 2 : 4;
	// BUG: possible unsigned integer overflow here
	attr->info.code_attr.code_offset = buf_offset + offset;
	attr->info.code_attr.code = (ut8 *) malloc (attr->info.code_attr.code_length);
	if (!attr->info.code_attr.code) {
		eprintf ("Handling Code Attributes: Unable to allocate memory "
			"(%u bytes) for a code.\n", attr->info.code_attr.code_length);
		return attr;
	}
	R_BIN_JAVA_GLOBAL_BIN->current_code_attr = attr;
	{
		int len = attr->info.code_attr.code_length;
		memset (attr->info.code_attr.code, 0, len);
		if (offset + len >= sz) {
			return attr;
		}
		memcpy (attr->info.code_attr.code, buffer + offset, len);
		offset += len;
	}
	attr->info.code_attr.exception_table_length = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.code_attr.exception_table = r_list_newf (free);
	for (k = 0; k < attr->info.code_attr.exception_table_length; k++) {
		curpos = buf_offset + offset;
		if (curpos + 8 > sz) {
			return attr;
		}
		RBinJavaExceptionEntry *e = R_NEW0 (RBinJavaExceptionEntry);
		if (!e) {
			free (attr);
			return NULL;
		}
		e->file_offset = curpos;
		e->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		e->end_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		e->handler_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		e->catch_type = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		r_list_append (attr->info.code_attr.exception_table, e);
		e->size = 8;
	}
	attr->info.code_attr.attributes_count = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	// IFDBG eprintf ("	code Attributes_count: %d\n", attr->info.code_attr.attributes_count);
	// XXX - attr->info.code_attr.attributes is not freed because one of the code attributes is improperly parsed.
	attr->info.code_attr.attributes = r_list_newf (r_bin_java_attribute_free);
	if (attr->info.code_attr.attributes_count > 0) {
		for (k = 0; k < attr->info.code_attr.attributes_count; k++) {
			int size = (offset < sz) ? sz - offset : 0;
			if (size > sz || size <= 0) {
				break;
			}
			_attr = r_bin_java_read_next_attr_from_buffer (bin, buffer + offset, size, buf_offset + offset);
			if (!_attr) {
				eprintf ("[X] r_bin_java_code_attr_new: Error unable to parse remainder of classfile after Method's Code Attribute: %d.\n", k);
				break;
			}
			IFDBG eprintf("Parsing @ 0x%"PFMT64x " (%s) = 0x%"PFMT64x " bytes, %p\n", _attr->file_offset, _attr->name, _attr->size, _attr);
			offset += _attr->size;
			r_list_append (attr->info.code_attr.attributes, _attr);
			if (_attr->type == R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TABLE_ATTR) {
				IFDBG eprintf("Parsed the LocalVariableTable, preparing the implicit mthod frame.\n");
				// r_bin_java_print_attr_summary(_attr);
				attr->info.code_attr.implicit_frame = r_bin_java_build_stack_frame_from_local_variable_table (R_BIN_JAVA_GLOBAL_BIN, _attr);
				attr->info.code_attr.implicit_frame->file_offset = buf_offset;
				IFDBG r_bin_java_print_stack_map_frame_summary(attr->info.code_attr.implicit_frame);
				// r_list_append (attr->info.code_attr.attributes, attr->info.code_attr.implicit_frame);
			}
			// if (offset > sz) {
			// eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Attribute: %d.\n", k);
			// break;
			// }

		}
	}
	if (attr->info.code_attr.implicit_frame == NULL) {
		// build a default implicit_frame
		attr->info.code_attr.implicit_frame = r_bin_java_default_stack_frame ();
		// r_list_append (attr->info.code_attr.attributes, attr->info.code_attr.implicit_frame);
	}
	attr->size = offset;
	return attr;
}

Project: radare2

R_API RBinJavaAttrInfo *r_bin_java_stack_map_table_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	ut64 offset = 0;
	RBinJavaStackMapFrame *stack_frame = NULL, *new_stack_frame = NULL;
	if (sz < 10) {
		return NULL;
	}
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
	offset += 6;
	IFDBG eprintf("r_bin_java_stack_map_table_attr_new: New stack map allocated.\n");
	if (!attr) {
		return NULL;
	}
	attr->info.stack_map_table_attr.stack_map_frame_entries = r_list_newf (r_bin_java_stack_frame_free);
	// IFDBG r_bin_java_print_source_code_file_attr_summary(attr);
	// Current spec does not call for variable sizes.
	attr->info.stack_map_table_attr.number_of_entries = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	IFDBG eprintf("r_bin_java_stack_map_table_attr_new: Processing stack map, summary is:\n");
	IFDBG r_bin_java_print_stack_map_table_attr_summary(attr);
	for (i = 0; i < attr->info.stack_map_table_attr.number_of_entries; i++) {
		// read next stack frame
		IFDBG eprintf("Reading StackMap Entry #%d @ 0x%08"PFMT64x "\n", i, buf_offset + offset);
		if (stack_frame == NULL && R_BIN_JAVA_GLOBAL_BIN && R_BIN_JAVA_GLOBAL_BIN->current_code_attr) {
			IFDBG eprintf("Setting an implicit frame at #%d @ 0x%08"PFMT64x "\n", i, buf_offset + offset);
			stack_frame = R_BIN_JAVA_GLOBAL_BIN->current_code_attr->info.code_attr.implicit_frame;
		}
		IFDBG eprintf("Reading StackMap Entry #%d @ 0x%08"PFMT64x ", current stack_frame: %p\n", i, buf_offset + offset, stack_frame);
		if (offset >= sz) {
			r_bin_java_stack_map_table_attr_free (attr);
			return NULL;
		}
		new_stack_frame = r_bin_java_stack_map_frame_new (buffer + offset, sz - offset, stack_frame, buf_offset + offset);
		if (new_stack_frame) {
			offset += new_stack_frame->size;
			// append stack frame to the list
			r_list_append (attr->info.stack_map_table_attr.stack_map_frame_entries, (void *) new_stack_frame);
			stack_frame = new_stack_frame;
		} else {
			eprintf ("r_bin_java_stack_map_table_attr_new: Unable to parse the stack frame for the stack map table.\n");
			r_bin_java_stack_map_table_attr_free (attr);
			attr = NULL;
			break;
		}
	}
	if (attr) {
		attr->size = offset;
	}
	return attr;
}

Project: radare2

R_API RBinSymbol *r_bin_java_create_new_symbol_from_ref(RBinJavaObj *bin, 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)) {
		R_FREE (sym);
		return sym;
	}
	if (sym) {
		class_name = r_bin_java_get_name_from_bin_cp_list (bin,
			obj->info.cp_method.class_idx);
		name = r_bin_java_get_name_from_bin_cp_list (bin,
			obj->info.cp_method.name_and_type_idx);
		type_name = r_bin_java_get_name_from_bin_cp_list (bin,
			obj->info.cp_method.name_and_type_idx);
		if (name) {
			sym->name = name;
			name = NULL;
		}
		if (type_name) {
			sym->type = r_str_constpool_get (&bin->constpool, 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

R_API char *r_bin_java_print_methodtype_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_method_type.descriptor_index);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				(void)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_method_type.descriptor_index);
			}
		}
	}
	return value;
}

Project: radare2

R_API RBinJavaAttrInfo *r_bin_java_local_variable_table_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaLocalVariableAttribute *lvattr;
	ut64 curpos = 0, offset = 6;
	RBinJavaAttrInfo *attr;
	ut32 i = 0;
	if (!buffer || sz < 1) {
		return NULL;
	}
	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
	if (!attr) {
		return NULL;
	}
	attr->type = R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TABLE_ATTR;
	attr->info.local_variable_table_attr.table_length = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.local_variable_table_attr.local_variable_table =\
		r_list_newf (r_bin_java_local_variable_table_attr_entry_free);
	for (i = 0; i < attr->info.local_variable_table_attr.table_length; i++) {
		if (offset + 10 > sz) {
			break;
		}
		curpos = buf_offset + offset;
		lvattr = R_NEW0 (RBinJavaLocalVariableAttribute);
		lvattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->length = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->name_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->descriptor_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->index = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->file_offset = curpos;
		lvattr->name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, lvattr->name_idx);
		lvattr->size = 10;
		if (!lvattr->name) {
			lvattr->name = strdup ("NULL");
			eprintf ("r_bin_java_local_variable_table_attr_new: Unable to find the name for %d index.\n", lvattr->name_idx);
		}
		lvattr->descriptor = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, lvattr->descriptor_idx);
		if (!lvattr->descriptor) {
			lvattr->descriptor = strdup ("NULL");
			eprintf ("r_bin_java_local_variable_table_attr_new: Unable to find the descriptor for %d index.\n", lvattr->descriptor_idx);
		}
		r_list_append (attr->info.local_variable_table_attr.local_variable_table, lvattr);
	}
	attr->size = offset;
	// IFDBG r_bin_java_print_local_variable_table_attr_summary(attr);
	return attr;
}

Project: radare2

R_API RBinJavaAttrInfo *r_bin_java_exceptions_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0, offset = 0;
	ut64 size;
	RBinJavaAttrInfo *attr = NULL;
	if (sz < 8) {
		return NULL;
	}
	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
	offset += 6;
	if (!attr) {
		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++) {
		if (offset + 2 > sz) {
			break;
		}
		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

R_API RBinJavaAttrInfo *r_bin_java_default_attr_new(RBinJavaObj *bin, 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->is_attr_in_old_format = r_bin_java_is_old_format(bin);
	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

R_API RBinJavaAttrInfo *r_bin_java_signature_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut64 offset = 6;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, 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

R_API void r_bin_java_print_annotation_summary(RBinJavaAnnotation *annotation) {
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaElementValuePair *evp = NULL;
	if (!annotation) {
		// TODO eprintf invalid annotation
		return;
	}
	Eprintf ("  Annotation Type Index: 0x%02x\n", annotation->type_idx);
	Eprintf ("  Annotation Number of EV Pairs: 0x%04x\n", annotation->num_element_value_pairs);
	Eprintf ("  Annotation EV Pair Values:\n");
	if (annotation->element_value_pairs) {
		r_list_foreach_safe (annotation->element_value_pairs, iter, iter_tmp, evp) {
			r_bin_java_print_element_pair_summary (evp);
		}
	}
}

Project: radare2

R_API void r_bin_java_print_element_pair_summary(RBinJavaElementValuePair *evp) {
	if (!evp) {
		eprintf ("Attempting to print an invalid RBinJavaElementValuePair *pair.\n");
		return;
	}
	Eprintf ("Element Value Pair information:\n");
	Eprintf ("  EV Pair File Offset: 0x%08"PFMT64x "\n", evp->file_offset);
	Eprintf ("  EV Pair Element Name index: 0x%02x\n", evp->element_name_idx);
	Eprintf ("  EV Pair Element Name: %s\n", evp->name);
	Eprintf ("  EV Pair Element Value:\n");
	r_bin_java_print_element_value_summary (evp->value);
}

Project: radare2

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);
				(void)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

R_API RBinJavaAttrInfo *r_bin_java_line_number_table_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	ut64 curpos, offset = 0;
	RBinJavaLineNumberAttribute *lnattr;
	if (sz < 6) {
		return NULL;
	}
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
	if (!attr) {
		return NULL;
	}
	offset += 6;
	attr->type = R_BIN_JAVA_ATTR_TYPE_LINE_NUMBER_TABLE_ATTR;
	attr->info.line_number_table_attr.line_number_table_length = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.line_number_table_attr.line_number_table = r_list_newf (free);

	ut32 linenum_len = attr->info.line_number_table_attr.line_number_table_length;
	RList *linenum_list = attr->info.line_number_table_attr.line_number_table;
	for (i = 0; i < linenum_len; i++) {
		curpos = buf_offset + offset;
		// eprintf ("%"PFMT64x" %"PFMT64x"\n", curpos, sz);
		// XXX if (curpos + 8 >= sz) break;
		lnattr = R_NEW0 (RBinJavaLineNumberAttribute);
		if (!lnattr) {
			break;
		}
		// wtf it works
		if (offset - 2 > sz) {
			R_FREE (lnattr);
			break;
		}
		lnattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lnattr->line_number = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lnattr->file_offset = curpos;
		lnattr->size = 4;
		r_list_append (linenum_list, lnattr);
	}
	attr->size = offset;
	return attr;
}

Project: radare2

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);
				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s",
					obj->metas->ord, obj->file_offset,
					((RBinJavaCPTypeMetas *) obj->metas->type_info)->name);
			}
		}
	}
	return value;
}

Project: radare2

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);
				(void)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

R_API RBinJavaStackMapFrame *r_bin_java_stack_map_frame_new(ut8 *buffer, ut64 sz, RBinJavaStackMapFrame *p_frame, ut64 buf_offset) {
	RBinJavaStackMapFrame *stack_frame = r_bin_java_default_stack_frame ();
	RBinJavaVerificationObj *se = NULL;
	ut64 offset = 0;
	if (!stack_frame) {
		return NULL;
	}
	stack_frame->tag = buffer[offset];
	offset += 1;
	stack_frame->metas->type_info = (void *) r_bin_java_determine_stack_frame_type (stack_frame->tag);
	stack_frame->type = ((RBinJavaStackMapFrameMetas *) stack_frame->metas->type_info)->type;
	stack_frame->file_offset = buf_offset;
	stack_frame->p_stack_frame = p_frame;
	switch (stack_frame->type) {
	case R_BIN_JAVA_STACK_FRAME_SAME:
		// Maybe?  1. Copy the previous frames locals and set the locals count.
		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
		if (p_frame) {
			stack_frame->number_of_locals = p_frame->number_of_locals;
		} else {
			IFINT eprintf("><?><\n");
			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Same Locals Condition is untested, so there may be issues.\n");
		break;
	case R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1:
		// 1. Read the stack type
		stack_frame->number_of_stack_items = 1;
		if (offset > sz) {
			r_bin_java_stack_frame_free (stack_frame);
			return NULL;
		}
		se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsed R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1.\n");
		if (se) {
			offset += se->size;
		} else {
			eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the Stack Items for the stack frame.\n");
			r_bin_java_stack_frame_free (stack_frame);
			return NULL;
		}
		r_list_append (stack_frame->stack_items, (void *) se);
		// Maybe?  3. Copy the previous frames locals and set the locals count.
		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
		if (p_frame) {
			stack_frame->number_of_locals = p_frame->number_of_locals;
		} else {
			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Same Locals 1 Stack Element Condition is untested, so there may be issues.\n");
		break;
	case R_BIN_JAVA_STACK_FRAME_CHOP:
		// 1. Calculate the max index we want to copy from the list of the
		// previous frames locals
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_CHOP.\n");
		// ut16 k = 251 - stack_frame->tag;
		/*,
		idx = p_frame->number_of_locals - k;
		*/
		// 2.  read the uoffset value
		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// Maybe? 3. Copy the previous frames locals and set the locals count.
		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
		if (p_frame) {
			stack_frame->number_of_locals = p_frame->number_of_locals;
		} else {
			IFINT eprintf("><?><\n");
			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Chop Condition is untested, so there may be issues.\n");
		break;
	case R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED:
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED.\n");
		// 1. Read the uoffset
		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// 2. Read the stack element type
		stack_frame->number_of_stack_items = 1;
		se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
		if (se) {
			offset += se->size;
		} else {
			eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the Stack Items for the stack frame.\n");
			r_bin_java_stack_frame_free (stack_frame);
			return NULL;
		}
		r_list_append (stack_frame->stack_items, (void *) se);
		// Maybe? 3. Copy the previous frames locals to the current locals
		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
		if (p_frame) {
			stack_frame->number_of_locals = p_frame->number_of_locals;
		} else {
			IFINT eprintf("><?><\n");
			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Same Locals Frame Stack 1 Extended Condition is untested, so there may be issues.\n");
		break;
	case R_BIN_JAVA_STACK_FRAME_APPEND:
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_APPEND.\n");
		// 1. Calculate the max index we want to copy from the list of the
		// previous frames locals
		ut16 k = stack_frame->tag - 251;
		ut32 i = 0;
		// 2. Read the uoffset
		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// Maybe? 3. Copy the previous frames locals to the current locals
		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
		// 4. Read off the rest of the appended locals types
		for (i = 0; i < k; i++) {
			if (offset >= sz) {
				break;
			}
			IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing verifying the k'th frame: %d of %d.\n", i, k);
			se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
			IFDBG eprintf("r_bin_java_stack_map_frame_new: Completed Parsing\n");
			if (se) {
				offset += se->size;
			} else {
				eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the locals for the stack frame.\n");
				r_bin_java_stack_frame_free (stack_frame);
				return NULL;
			}
			r_list_append (stack_frame->local_items, (void *) se);
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Breaking out of loop");
		IFDBG eprintf("p_frame: %p\n", p_frame);
		if (p_frame) {
			stack_frame->number_of_locals = p_frame->number_of_locals + k;
		} else {
			IFINT eprintf("><?><\n");
			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Same Locals Frame Stack 1 Extended Condition is untested, so there may be issues.\n");
		break;
	case R_BIN_JAVA_STACK_FRAME_FULL_FRAME:
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_FULL_FRAME.\n");
		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// IFDBG eprintf ("r_bin_java_stack_map_frame_new: Code Size > 65535, read(%d byte(s)), offset = 0x%08x.\n", var_sz, stack_frame->offset_delta);
		// Read the number of variables based on the max # local variable
		stack_frame->number_of_locals = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// IFDBG eprintf ("r_bin_java_stack_map_frame_new: Max ulocalvar > 65535, read(%d byte(s)), number_of_locals = 0x%08x.\n", var_sz, stack_frame->number_of_locals);
		IFDBG r_bin_java_print_stack_map_frame_summary(stack_frame);
		// read the number of locals off the stack
		for (i = 0; i < stack_frame->number_of_locals; i++) {
			if (offset >= sz) {
				break;
			}
			se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
			if (se) {
				offset += se->size;
				// r_list_append (stack_frame->local_items, (void *) se);
			} else {
				eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the locals for the stack frame.\n");
				r_bin_java_stack_frame_free (stack_frame);
				return NULL;
			}
			r_list_append (stack_frame->local_items, (void *) se);
		}
		// Read the number of stack items based on the max size of stack
		stack_frame->number_of_stack_items = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// IFDBG eprintf ("r_bin_java_stack_map_frame_new: Max ustack items > 65535, read(%d byte(s)), number_of_locals = 0x%08x.\n", var_sz, stack_frame->number_of_stack_items);
		// read the stack items
		for (i = 0; i < stack_frame->number_of_stack_items; i++) {
			if (offset >= sz) {
				break;
			}
			se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
			if (se) {
				offset += se->size;
				// r_list_append (stack_frame->stack_items, (void *) se);
			} else {
				eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the stack items for the stack frame.\n");
				r_bin_java_stack_frame_free (stack_frame);
				return NULL;
			}
			r_list_append (stack_frame->local_items, (void *) se);
		}
		break;
	default:
		eprintf ("java: Unknown type\n");
		break;
	}
	// IFDBG eprintf ("Created a stack frame at offset(0x%08"PFMT64x") of size: %d\n", buf_offset, stack_frame->size);//r_bin_java_print_stack_map_frame_summary(stack_frame);
	stack_frame->size = offset;
	// IFDBG r_bin_java_print_stack_map_frame_summary(stack_frame);
	return stack_frame;
}

Project: radare2

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) {
		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

R_API ut64 r_bin_java_element_value_calc_size(RBinJavaElementValue *element_value) {
	RListIter *iter, *iter_tmp;
	RBinJavaElementValue *ev_element;
	RBinJavaElementValuePair *evps;
	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, evps) {
			if (evps) {
				sz += r_bin_java_element_pair_calc_size (evps);
			}
		}
		break;
	default:
		// eprintf unable to handle tag
		break;
	}
	return sz;
}

Project: radare2

R_API RBinJavaElementValuePair *r_bin_java_element_pair_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	if (!buffer || sz < 4) {
		return NULL;
	}
	RBinJavaElementValuePair *evp = R_NEW0 (RBinJavaElementValuePair);
	if (!evp) {
		return NULL;
	}
	// TODO: What is the signifigance of evp element
	evp->element_name_idx = R_BIN_JAVA_USHORT (buffer, 0);
	ut64 offset = 2;
	evp->file_offset = buf_offset;
	evp->name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, evp->element_name_idx);
	if (!evp->name) {
		// TODO: eprintf unable to find the name for the given index
		eprintf ("ElementValue Name is invalid.\n");
		evp->name = strdup ("UNKNOWN");
	}
	if (offset >= sz) {
		free (evp);
		return NULL;
	}
	evp->value = r_bin_java_element_value_new (buffer + offset, sz - offset, buf_offset + offset);
	offset += evp->value->size;
	if (offset >= sz) {
		free (evp->value);
		free (evp);
		return NULL;
	}
	evp->size = offset;
	return evp;
}

Project: radare2

R_API RBinJavaAttrInfo *r_bin_java_inner_classes_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaClassesAttribute *icattr;
	RBinJavaAttrInfo *attr = NULL;
	RBinJavaCPTypeObj *obj;
	ut32 i = 0;
	ut64 offset = 0, curpos;
	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
	offset += 6;
	if (buf_offset + offset + 8 > sz) {
		eprintf ("Invalid amount of inner classes\n");
		return NULL;
	}
	if (attr == NULL) {
		// TODO eprintf
		return attr;
	}
	attr->type = R_BIN_JAVA_ATTR_TYPE_INNER_CLASSES_ATTR;
	attr->info.inner_classes_attr.number_of_classes = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.inner_classes_attr.classes = r_list_newf (r_bin_java_inner_classes_attr_entry_free);
	for (i = 0; i < attr->info.inner_classes_attr.number_of_classes; i++) {
		curpos = buf_offset + offset;
		if (buf_offset + offset + 8 > sz) {
			eprintf ("Invalid amount of inner classes\n");
			break;
		}
		icattr = R_NEW0 (RBinJavaClassesAttribute);
		if (!icattr) {
			break;
		}
		icattr->inner_class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		icattr->outer_class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		icattr->inner_name_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		icattr->inner_class_access_flags = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		icattr->flags_str = retrieve_class_method_access_string (icattr->inner_class_access_flags);
		icattr->file_offset = curpos;
		icattr->size = 8;

		obj = r_bin_java_get_item_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, icattr->inner_name_idx);
		if (obj == NULL) {
			eprintf ("BINCPLIS IS HULL %d\n", icattr->inner_name_idx);
		}
		icattr->name = r_bin_java_get_item_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, obj);
		if (!icattr->name) {
			obj = r_bin_java_get_item_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, icattr->inner_class_info_idx);
			if (!obj) {
				eprintf ("BINCPLIST IS NULL %d\n", icattr->inner_class_info_idx);
			}
			icattr->name = r_bin_java_get_item_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, obj);
			if (!icattr->name) {
				icattr->name = r_str_dup (NULL, "NULL");
				eprintf ("r_bin_java_inner_classes_attr: Unable to find the name for %d index.\n", icattr->inner_name_idx);
				free (icattr);
				break;
			}
		}

		IFDBG eprintf("r_bin_java_inner_classes_attr: Inner class name %d is %s.\n", icattr->inner_name_idx, icattr->name);
		r_list_append (attr->info.inner_classes_attr.classes, (void *) icattr);
	}
	attr->size = offset;
	// IFDBG r_bin_java_print_inner_classes_attr_summary(attr);
	return attr;
}

Project: radare2

R_API RBinJavaAttrInfo *r_bin_java_read_next_attr_from_buffer(RBinJavaObj *bin, ut8 *buffer, st64 sz, st64 buf_offset) {
	RBinJavaAttrInfo *attr = NULL;
	ut64 offset = 0;
	ut16 name_idx;
	st64 nsz;

	if (!buffer || ((int) sz) < 4 || buf_offset < 0) {
		eprintf ("r_bin_Java_read_next_attr_from_buffer: invalid buffer size %d\n", (int) sz);
		return NULL;
	}
	name_idx = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	nsz = R_BIN_JAVA_UINT (buffer, offset);
	// DEAD INCREMENT offset += 4;

	char *name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, name_idx);
	if (!name) {
		name = strdup ("unknown");
	}
	IFDBG eprintf("r_bin_java_read_next_attr: name_idx = %d is %s\n", name_idx, name);
	RBinJavaAttrMetas *type_info = r_bin_java_get_attr_type_by_name (name);
	if (type_info) {
		IFDBG eprintf("Typeinfo: %s, was %s\n", type_info->name, name);
		// printf ("SZ %d %d %d\n", nsz, sz, buf_offset);
		if (nsz > sz) {
			free (name);
			return NULL;
		}
		if ((attr = type_info->allocs->new_obj (bin, buffer, nsz, buf_offset))) {
			attr->metas->ord = (R_BIN_JAVA_GLOBAL_BIN->attr_idx++);
		}
	} else {
		eprintf ("r_bin_java_read_next_attr_from_buffer: Cannot find type_info for %s\n", name);
	}
	free (name);
	return attr;
}

Project: radare2

R_API char *r_bin_java_print_methodhandle_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	ut8 ref_kind = obj->info.cp_method_handle.reference_kind;
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%s.%d",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			R_BIN_JAVA_REF_METAS[ref_kind].name, obj->info.cp_method_handle.reference_index);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%s.%d",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					R_BIN_JAVA_REF_METAS[ref_kind].name, obj->info.cp_method_handle.reference_index);
			}
		}
	}
	return value;
}

Project: radare2

R_API RBinJavaAttrInfo *r_bin_java_deprecated_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaAttrInfo *attr = NULL;
	ut64 offset = 0;
	attr = r_bin_java_default_attr_new (bin, 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

R_API char *r_bin_java_print_interfacemethodref_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_interface.class_idx, obj->info.cp_interface.name_and_type_idx);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				(void)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_interface.class_idx, obj->info.cp_interface.name_and_type_idx);
			}
		}
	}
	return value;
}

Project: radare2

R_API RBinJavaAttrInfo *r_bin_java_read_next_attr(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 buf_len) {
	RBinJavaAttrInfo *attr = NULL;
	ut32 sz = 0;
	ut8 *buffer = NULL;
	const ut8 *a_buf = offset + buf;
	ut8 attr_idx_len = 6;
	if (offset + 6 > buf_len) {
		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile in Attribute offset "
			"(0x%"PFMT64x ") > len  of remaining bytes (0x%"PFMT64x ").\n", offset, buf_len);
		return NULL;
	}
	// ut16 attr_idx, ut32 length of attr.
	sz = R_BIN_JAVA_UINT (a_buf, 2) + attr_idx_len; // r_bin_java_read_int (bin, buf_offset+2) + attr_idx_len;
	if (sz + offset > buf_len) {
		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile in Attribute len "
			"(0x%x) + offset (0x%"PFMT64x ") exceeds length of buffer (0x%"PFMT64x ").\n",
			sz, offset, buf_len);
		return NULL;
	}
	// when reading the attr bytes, need to also
	// include the initial 6 bytes, which
	// are not included in the attribute length
	// ,
	// sz, buf_offset, buf_offset+sz);
	buffer = r_bin_java_get_attr_buf (bin, sz, offset, buf, buf_len);
	// printf ("%d %d %d\n", sz, buf_len, offset);
	if (offset < buf_len) {
		attr = r_bin_java_read_next_attr_from_buffer (bin, buffer, buf_len - offset, offset);
		free (buffer);

		if (!attr) {
			return NULL;
		}
		attr->size = sz;
	} else {
		free (buffer);
		eprintf ("IS OOB\n");
	}
	return attr;
}

Project: radare2

R_API void r_bin_java_reset_bin_info(RBinJavaObj *bin) {
	free (bin->cf2.flags_str);
	free (bin->cf2.this_class_name);
	r_list_free (bin->imports_list);
	r_list_free (bin->methods_list);
	r_list_free (bin->fields_list);
	r_list_free (bin->attrs_list);
	r_list_free (bin->cp_list);
	r_list_free (bin->interfaces_list);
	r_str_constpool_fini (&bin->constpool);
	memset (bin, 0, sizeof (RBinJavaObj));
	r_str_constpool_init (&bin->constpool);
	bin->cf2.flags_str = strdup ("unknown");
	bin->cf2.this_class_name = strdup ("unknown");
	bin->imports_list = r_list_newf (free);
	bin->methods_list = r_list_newf (r_bin_java_fmtype_free);
	bin->fields_list = r_list_newf (r_bin_java_fmtype_free);
	bin->attrs_list = r_list_newf (r_bin_java_attribute_free);
	bin->cp_list = r_list_newf (r_bin_java_constant_pool);
	bin->interfaces_list = r_list_newf (r_bin_java_interface_free);
}