< prev index next >

src/hotspot/share/classfile/verifier.cpp

Print this page
rev 55090 : secret-sfac

@@ -1677,11 +1677,11 @@
                          "Method expects a return value");
             return;
           }
           // Make sure "this" has been initialized if current method is an
           // <init>.
-          if (_method->name() == vmSymbols::object_initializer_name() &&
+          if (_method->is_object_constructor() &&
               current_frame.flag_this_uninit()) {
             verify_error(ErrorContext::bad_code(bci),
                          "Constructor must call super() or this() "
                          "before return");
             return;

@@ -1713,17 +1713,17 @@
         case Bytecodes::_invokevirtual :
         case Bytecodes::_invokespecial :
         case Bytecodes::_invokestatic :
           verify_invoke_instructions(
             &bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
-            &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
+            &this_uninit, cp, &stackmap_table, CHECK_VERIFY(this));
           no_control_flow = false; break;
         case Bytecodes::_invokeinterface :
         case Bytecodes::_invokedynamic :
           verify_invoke_instructions(
             &bcs, code_length, &current_frame, (bci >= ex_min && bci < ex_max),
-            &this_uninit, return_type, cp, &stackmap_table, CHECK_VERIFY(this));
+            &this_uninit, cp, &stackmap_table, CHECK_VERIFY(this));
           no_control_flow = false; break;
         case Bytecodes::_new :
         {
           index = bcs.get_index_u2();
           verify_cp_class_type(bci, index, cp, CHECK_VERIFY(this));

@@ -2817,11 +2817,11 @@
   return false;
 }
 
 void ClassVerifier::verify_invoke_instructions(
     RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,
-    bool in_try_block, bool *this_uninit, VerificationType return_type,
+    bool in_try_block, bool *this_uninit,
     const constantPoolHandle& cp, StackMapTable* stackmap_table, TRAPS) {
   // Make sure the constant pool item is the right type
   u2 index = bcs->get_index_u2();
   Bytecodes::Code opcode = bcs->raw_code();
   unsigned int types = 0;

@@ -2915,12 +2915,14 @@
       return;
     }
   }
 
   if (method_name->char_at(0) == '<') {
-    // Make sure <init> can only be invoked by invokespecial
-    if (opcode != Bytecodes::_invokespecial ||
+    // Make sure <init> can only be invoked by invokespecial or invokestatic.
+    // The allowed invocation mode of <init> depends on its signature.
+    if ((opcode != Bytecodes::_invokespecial &&
+         opcode != Bytecodes::_invokestatic) ||
         method_name != vmSymbols::object_initializer_name()) {
       verify_error(ErrorContext::bad_code(bci),
           "Illegal call to internal method");
       return;
     }

@@ -2970,10 +2972,11 @@
 
   // Check objectref on operand stack
   if (opcode != Bytecodes::_invokestatic &&
       opcode != Bytecodes::_invokedynamic) {
     if (method_name == vmSymbols::object_initializer_name()) {  // <init> method
+      // (use of <init> as a static factory is handled under invokestatic)
       verify_invoke_init(bcs, index, ref_class_type, current_frame,
         code_length, in_try_block, this_uninit, cp, stackmap_table,
         CHECK_VERIFY(this));
       if (was_recursively_verified()) return;
     } else {   // other methods

@@ -3040,14 +3043,13 @@
     }
   }
   // Push the result type.
   int sig_verif_types_len = sig_verif_types->length();
   if (sig_verif_types_len > nargs) {  // There's a return type
-    if (method_name == vmSymbols::object_initializer_name()) {
-      // <init> method must have a void return type
-      /* Unreachable?  Class file parser verifies that methods with '<' have
-       * void return */
+    if (method_name == vmSymbols::object_initializer_name() &&
+        opcode != Bytecodes::_invokestatic) {
+      // an <init> method must have a void return type, unless it's a static factory
       verify_error(ErrorContext::bad_code(bci),
           "Return type must be void in <init> method");
       return;
     }
 

@@ -3056,10 +3058,18 @@
     for (int i = nargs; i < sig_verif_types_len; i++) {
       assert(i == nargs || sig_verif_types->at(i).is_long2() ||
              sig_verif_types->at(i).is_double2(), "Unexpected return verificationType");
       current_frame->push_stack(sig_verif_types->at(i), CHECK_VERIFY(this));
     }
+  } else {
+    // an <init> method may not have a void return type, if it's a static factory
+    if (method_name == vmSymbols::object_initializer_name() &&
+        opcode != Bytecodes::_invokespecial) {
+      verify_error(ErrorContext::bad_code(bci),
+          "Return type must be non-void in <init> static factory method");
+      return;
+    }
   }
 }
 
 VerificationType ClassVerifier::get_newarray_type(
     u2 index, u2 bci, TRAPS) {
< prev index next >