hotspot/src/share/vm/classfile/classFileParser.cpp
changeset 15464 1f2cca0aa501
parent 15244 83447fffce1e
child 15601 df8faef6efaf
--- a/hotspot/src/share/vm/classfile/classFileParser.cpp	Sun Feb 03 17:12:31 2013 -0500
+++ b/hotspot/src/share/vm/classfile/classFileParser.cpp	Mon Feb 04 13:05:32 2013 -0500
@@ -1947,6 +1947,8 @@
   u2** localvariable_type_table_start;
   u2 method_parameters_length = 0;
   u1* method_parameters_data = NULL;
+  bool method_parameters_seen = false;
+  bool method_parameters_four_byte_flags;
   bool parsed_code_attribute = false;
   bool parsed_checked_exceptions_attribute = false;
   bool parsed_stackmap_attribute = false;
@@ -2157,21 +2159,31 @@
                                      method_attribute_length,
                                      cp, CHECK_(nullHandle));
     } 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();
       // Track the actual size (note: this is written for clarity; a
       // decent compiler will CSE and constant-fold this into a single
       // expression)
-      u2 actual_size = 1;
+      // Use the attribute length to figure out the size of flags
+      if (method_attribute_length == (method_parameters_length * 6u) + 1u) {
+        method_parameters_four_byte_flags = true;
+      } else if (method_attribute_length == (method_parameters_length * 4u) + 1u) {
+        method_parameters_four_byte_flags = false;
+      } else {
+        classfile_parse_error(
+          "Invalid MethodParameters method attribute length %u in class file",
+          method_attribute_length, CHECK_(nullHandle));
+      }
       method_parameters_data = cfs->get_u1_buffer();
-      actual_size += 2 * method_parameters_length;
       cfs->skip_u2_fast(method_parameters_length);
-      actual_size += 4 * method_parameters_length;
-      cfs->skip_u4_fast(method_parameters_length);
-      // Enforce attribute length
-      if (method_attribute_length != actual_size) {
-        classfile_parse_error(
-          "Invalid MethodParameters method attribute length %u in class file %s",
-          method_attribute_length, CHECK_(nullHandle));
+      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
       if (!SystemDictionary::Parameter_klass_loaded())
@@ -2316,15 +2328,16 @@
   // Copy method parameters
   if (method_parameters_length > 0) {
     MethodParametersElement* elem = m->constMethod()->method_parameters_start();
-    for(int i = 0; i < method_parameters_length; i++) {
-      elem[i].name_cp_index =
-        Bytes::get_Java_u2(method_parameters_data);
+    for (int i = 0; i < method_parameters_length; i++) {
+      elem[i].name_cp_index = Bytes::get_Java_u2(method_parameters_data);
       method_parameters_data += 2;
-      u4 flags = Bytes::get_Java_u4(method_parameters_data);
-      // This caused an alignment fault on Sparc, if flags was a u4
-      elem[i].flags_lo = extract_low_short_from_int(flags);
-      elem[i].flags_hi = extract_high_short_from_int(flags);
-      method_parameters_data += 4;
+      if (method_parameters_four_byte_flags) {
+        elem[i].flags = Bytes::get_Java_u4(method_parameters_data);
+        method_parameters_data += 4;
+      } else {
+        elem[i].flags = Bytes::get_Java_u2(method_parameters_data);
+        method_parameters_data += 2;
+      }
     }
   }