< prev index next >

src/share/vm/classfile/classFileParser.cpp

Print this page

        

@@ -103,10 +103,16 @@
 // Extension method support.
 #define JAVA_8_VERSION                    52
 
 #define JAVA_9_VERSION                    53
 
+void ClassFileParser::set_class_bad_constant_seen(short bad_constant) {
+  assert((bad_constant == 19 || bad_constant == 20) && _major_version >= JAVA_9_VERSION,
+         "Unexpected bad constant pool entry");
+  if (_bad_constant_seen == 0) _bad_constant_seen = bad_constant;
+}
+
 void ClassFileParser::parse_constant_pool_entries(const ClassFileStream* const stream,
                                                   ConstantPool* cp,
                                                   const int length,
                                                   TRAPS) {
   assert(stream != NULL, "invariant");

@@ -300,10 +306,22 @@
         } else {
           cp->symbol_at_put(index, result);
         }
         break;
       }
+      case 19:
+      case 20: {
+        // Record that an error occured in these two cases but keep parsing so
+        // that ACC_Module can be checked for in the access_flags.  Need to
+        // throw NoClassDefFoundError in that case.
+        if (_major_version >= JAVA_9_VERSION) {
+          cfs->guarantee_more(3, CHECK);
+          cfs->get_u2_fast();
+          set_class_bad_constant_seen(tag);
+          break;
+        }
+      }
       default: {
         classfile_parse_error("Unknown constant tag %u in class file %s",
                               tag,
                               CHECK);
         break;

@@ -365,10 +383,20 @@
   assert(cp != NULL, "invariant");
   assert(stream != NULL, "invariant");
 
   // parsing constant pool entries
   parse_constant_pool_entries(stream, cp, length, CHECK);
+  short bad_constant = class_bad_constant_seen();
+  if (bad_constant != 0) {
+    // Either a CONSTANT_Module or CONSTANT_Package entry was found in the constant
+    // pool.  So, stop parsing and return.  The caller will decide whether to throw
+    // NCDFE if it finds ACC_MODULE in the class's access_flags or throw CFE for
+    // the bad constant pool entry.
+    assert((bad_constant == 19 || bad_constant == 20) && _major_version >= JAVA_9_VERSION,
+           "Unexpected bad constant pool entry");
+    return;
+  }
 
   int index = 1;  // declared outside of loops for portability
 
   // first verification pass - validate cross references
   // and fixup class and string constants

@@ -5556,10 +5584,11 @@
   _num_miranda_methods(0),
   _rt(REF_NONE),
   _protection_domain(protection_domain),
   _access_flags(),
   _pub_level(pub_level),
+  _bad_constant_seen(0),
   _synthetic_flag(false),
   _sde_length(false),
   _sde_buffer(NULL),
   _sourcefile_index(0),
   _generic_signature_index(0),

@@ -5763,12 +5792,18 @@
     flags |= JVM_ACC_ABSTRACT;
   }
 
   verify_legal_class_modifiers(flags, CHECK);
 
-  _access_flags.set_flags(flags);
+  short bad_constant = class_bad_constant_seen();
+  if (bad_constant != 0) {
+    // Do not throw CFE until after the access_flags are checked because if
+    // ACC_MODULE is set in the access flags, then NCDFE must be thrown, not CFE.
+    classfile_parse_error("Unknown constant tag %u in class file %s", bad_constant, CHECK);
+  }
 
+  _access_flags.set_flags(flags);
 
   // This class and superclass
   _this_class_index = stream->get_u2_fast();
   check_property(
     valid_cp_range(_this_class_index, cp_size) &&
< prev index next >