8006949: Update hotspot for MethodParameters format change

8006907: Hotspot should reject classfiles with multiple MethodParameters attributes

Update to Hotspot's processing of MethodParameters attributes in classfiles

Reviewed-by: coleenp, jrose
This commit is contained in:
Eric McCorkle 2013-02-04 13:05:32 -05:00
parent 6c6a537471
commit 16990e896a
3 changed files with 32 additions and 24 deletions

View file

@ -1947,6 +1947,8 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
u2** localvariable_type_table_start; u2** localvariable_type_table_start;
u2 method_parameters_length = 0; u2 method_parameters_length = 0;
u1* method_parameters_data = NULL; u1* method_parameters_data = NULL;
bool method_parameters_seen = false;
bool method_parameters_four_byte_flags;
bool parsed_code_attribute = false; bool parsed_code_attribute = false;
bool parsed_checked_exceptions_attribute = false; bool parsed_checked_exceptions_attribute = false;
bool parsed_stackmap_attribute = false; bool parsed_stackmap_attribute = false;
@ -2157,22 +2159,32 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
method_attribute_length, method_attribute_length,
cp, CHECK_(nullHandle)); cp, CHECK_(nullHandle));
} else if (method_attribute_name == vmSymbols::tag_method_parameters()) { } else if (method_attribute_name == vmSymbols::tag_method_parameters()) {
// reject multiple method parameters
if (method_parameters_seen) {
classfile_parse_error("Multiple MethodParameters attributes in class file %s", CHECK_(nullHandle));
}
method_parameters_seen = true;
method_parameters_length = cfs->get_u1_fast(); method_parameters_length = cfs->get_u1_fast();
// Track the actual size (note: this is written for clarity; a // Track the actual size (note: this is written for clarity; a
// decent compiler will CSE and constant-fold this into a single // decent compiler will CSE and constant-fold this into a single
// expression) // expression)
u2 actual_size = 1; // Use the attribute length to figure out the size of flags
method_parameters_data = cfs->get_u1_buffer(); if (method_attribute_length == (method_parameters_length * 6u) + 1u) {
actual_size += 2 * method_parameters_length; method_parameters_four_byte_flags = true;
cfs->skip_u2_fast(method_parameters_length); } else if (method_attribute_length == (method_parameters_length * 4u) + 1u) {
actual_size += 4 * method_parameters_length; method_parameters_four_byte_flags = false;
cfs->skip_u4_fast(method_parameters_length); } else {
// Enforce attribute length
if (method_attribute_length != actual_size) {
classfile_parse_error( classfile_parse_error(
"Invalid MethodParameters method attribute length %u in class file %s", "Invalid MethodParameters method attribute length %u in class file",
method_attribute_length, CHECK_(nullHandle)); method_attribute_length, CHECK_(nullHandle));
} }
method_parameters_data = cfs->get_u1_buffer();
cfs->skip_u2_fast(method_parameters_length);
if (method_parameters_four_byte_flags) {
cfs->skip_u4_fast(method_parameters_length);
} else {
cfs->skip_u2_fast(method_parameters_length);
}
// ignore this attribute if it cannot be reflected // ignore this attribute if it cannot be reflected
if (!SystemDictionary::Parameter_klass_loaded()) if (!SystemDictionary::Parameter_klass_loaded())
method_parameters_length = 0; method_parameters_length = 0;
@ -2316,15 +2328,16 @@ methodHandle ClassFileParser::parse_method(ClassLoaderData* loader_data,
// Copy method parameters // Copy method parameters
if (method_parameters_length > 0) { if (method_parameters_length > 0) {
MethodParametersElement* elem = m->constMethod()->method_parameters_start(); MethodParametersElement* elem = m->constMethod()->method_parameters_start();
for(int i = 0; i < method_parameters_length; i++) { for (int i = 0; i < method_parameters_length; i++) {
elem[i].name_cp_index = elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data);
Bytes::get_Java_u2(method_parameters_data);
method_parameters_data += 2; method_parameters_data += 2;
u4 flags = Bytes::get_Java_u4(method_parameters_data); if (method_parameters_four_byte_flags) {
// This caused an alignment fault on Sparc, if flags was a u4 elem[i].flags = Bytes::get_Java_u4(method_parameters_data);
elem[i].flags_lo = extract_low_short_from_int(flags);
elem[i].flags_hi = extract_high_short_from_int(flags);
method_parameters_data += 4; method_parameters_data += 4;
} else {
elem[i].flags = Bytes::get_Java_u2(method_parameters_data);
method_parameters_data += 2;
}
} }
} }

View file

@ -122,12 +122,7 @@ class ExceptionTableElement VALUE_OBJ_CLASS_SPEC {
class MethodParametersElement VALUE_OBJ_CLASS_SPEC { class MethodParametersElement VALUE_OBJ_CLASS_SPEC {
public: public:
u2 name_cp_index; u2 name_cp_index;
// This has to happen, otherwise it will cause SIGBUS from a u2 flags;
// misaligned u4 on some architectures (ie SPARC)
// because MethodParametersElements are only aligned mod 2
// within the ConstMethod container u2 flags_hi;
u2 flags_hi;
u2 flags_lo;
}; };
class KlassSizeStats; class KlassSizeStats;

View file

@ -1620,7 +1620,7 @@ JVM_ENTRY(jobjectArray, JVM_GetMethodParameters(JNIEnv *env, jobject method))
// For a 0 index, give a NULL symbol // For a 0 index, give a NULL symbol
Symbol* const sym = 0 != params[i].name_cp_index ? Symbol* const sym = 0 != params[i].name_cp_index ?
mh->constants()->symbol_at(params[i].name_cp_index) : NULL; mh->constants()->symbol_at(params[i].name_cp_index) : NULL;
int flags = build_int_from_shorts(params[i].flags_lo, params[i].flags_hi); int flags = params[i].flags;
oop param = Reflection::new_parameter(reflected_method, i, sym, oop param = Reflection::new_parameter(reflected_method, i, sym,
flags, CHECK_NULL); flags, CHECK_NULL);
result->obj_at_put(i, param); result->obj_at_put(i, param);