changeset 4084:8af48ff040c9

8051012: Regression in verifier for <init> method call from inside of a branch Summary: Fix stackmap matching for branches. Reviewed-by: coleenp, lfoltan, acorn
author hseigel
date Mon, 19 Jan 2015 05:28:21 +0000
parents 1c7abe33c11f
children c9b5ffda6970
files src/share/vm/classfile/stackMapTable.cpp src/share/vm/classfile/stackMapTable.hpp src/share/vm/classfile/verifier.cpp src/share/vm/classfile/verifier.hpp
diffstat 4 files changed, 16 insertions(+), 40 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/stackMapTable.cpp	Thu Nov 06 04:57:28 2014 -0800
+++ b/src/share/vm/classfile/stackMapTable.cpp	Mon Jan 19 05:28:21 2015 +0000
@@ -68,27 +68,29 @@
 
 bool StackMapTable::match_stackmap(
     StackMapFrame* frame, int32_t target,
-    bool match, bool update, TRAPS) const {
+    bool match, bool update, bool handler, TRAPS) const {
   int index = get_index_from_offset(target);
 
   return match_stackmap(
     frame, target, index, match,
-    update, CHECK_VERIFY_(frame->verifier(), false));
+    update, handler, CHECK_VERIFY_(frame->verifier(), false));
 }
 
 // Match and/or update current_frame to the frame in stackmap table with
 // specified offset and frame index. Return true if the two frames match.
+// handler is true if the frame in stackmap_table is for an exception handler.
 //
-// The values of match and update are:                  _match__update_
+// The values of match and update are:                  _match__update__handler
 //
-// checking a branch target/exception handler:           true   false
+// checking a branch target:                             true   false   false
+// checking an exception handler:                        true   false   true
 // linear bytecode verification following an
-// unconditional branch:                                 false  true
+// unconditional branch:                                 false  true    false
 // linear bytecode verification not following an
-// unconditional branch:                                 true   true
+// unconditional branch:                                 true   true    false
 bool StackMapTable::match_stackmap(
     StackMapFrame* frame, int32_t target, int32_t frame_index,
-    bool match, bool update, TRAPS) const {
+    bool match, bool update, bool handler, TRAPS) const {
   if (frame_index < 0 || frame_index >= _frame_count) {
     frame->verifier()->verify_error(frame->offset(),
       "Expecting a stackmap frame at branch target %d", target);
@@ -98,12 +100,10 @@
   bool result = true;
   StackMapFrame *stackmap_frame = _frame_array[frame_index];
   if (match) {
-    // when checking handler target, match == true && update == false
-    bool is_exception_handler = !update;
     // Has direct control flow from last instruction, need to match the two
     // frames.
     result = frame->is_assignable_to(
-      stackmap_frame, is_exception_handler,
+      stackmap_frame, handler,
       CHECK_VERIFY_(frame->verifier(), false));
   }
   if (update) {
@@ -126,7 +126,7 @@
 void StackMapTable::check_jump_target(
     StackMapFrame* frame, int32_t target, TRAPS) const {
   bool match = match_stackmap(
-    frame, target, true, false, CHECK_VERIFY(frame->verifier()));
+    frame, target, true, false, false, CHECK_VERIFY(frame->verifier()));
   if (!match || (target < 0 || target >= _code_length)) {
     frame->verifier()->verify_error(frame->offset(),
       "Inconsistent stackmap frames at branch target %d", target);
@@ -134,7 +134,6 @@
   }
   // check if uninitialized objects exist on backward branches
   check_new_object(frame, target, CHECK_VERIFY(frame->verifier()));
-  frame->verifier()->update_furthest_jump(target);
 }
 
 void StackMapTable::check_new_object(
--- a/src/share/vm/classfile/stackMapTable.hpp	Thu Nov 06 04:57:28 2014 -0800
+++ b/src/share/vm/classfile/stackMapTable.hpp	Mon Jan 19 05:28:21 2015 +0000
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,12 +73,12 @@
   // specified offset. Return true if the two frames match.
   bool match_stackmap(
     StackMapFrame* current_frame, int32_t offset,
-    bool match, bool update, TRAPS) const;
+    bool match, bool update, bool handler, TRAPS) const;
   // Match and/or update current_frame to the frame in stackmap table with
   // specified offset and frame index. Return true if the two frames match.
   bool match_stackmap(
     StackMapFrame* current_frame, int32_t offset, int32_t frame_index,
-    bool match, bool update, TRAPS) const;
+    bool match, bool update, bool handler, TRAPS) const;
 
   // Check jump instructions. Make sure there are no uninitialized
   // instances on backward branch.
--- a/src/share/vm/classfile/verifier.cpp	Thu Nov 06 04:57:28 2014 -0800
+++ b/src/share/vm/classfile/verifier.cpp	Mon Jan 19 05:28:21 2015 +0000
@@ -379,8 +379,6 @@
                                 // flow from current instruction to the next
                                 // instruction in sequence
 
-  set_furthest_jump(0);
-
   Bytecodes::Code opcode;
   while (!bcs.is_last_bytecode()) {
     // Check for recursive re-verification before each bytecode.
@@ -1455,7 +1453,7 @@
       // If matched, current_frame will be updated by this method.
       bool match = stackmap_table->match_stackmap(
         current_frame, this_offset, stackmap_index,
-        !no_control_flow, true, CHECK_VERIFY_(this, 0));
+        !no_control_flow, true, false, CHECK_VERIFY_(this, 0));
       if (!match) {
         // report type error
         verify_error(bci, "Instruction type does not match stack map");
@@ -1499,7 +1497,7 @@
           new_frame->push_stack(throwable, CHECK_VERIFY(this));
         }
         bool match = stackmap_table->match_stackmap(
-          new_frame, handler_pc, true, false, CHECK_VERIFY(this));
+	  new_frame, handler_pc, true, false, true, CHECK_VERIFY(this));
         if (!match) {
           verify_error(bci,
             "Stack map does not match the one at exception handler %d",
@@ -1895,12 +1893,6 @@
       return;
     }
 
-    // Make sure that this call is not jumped over.
-    if (bci < furthest_jump()) {
-      verify_error(bci, "Bad <init> method call from inside of a branch");
-      return;
-    }
-
     // Make sure that this call is not done from within a TRY block because
     // that can result in returning an incomplete object.  Simply checking
     // (bci >= start_pc) also ensures that this call is not done after a TRY
--- a/src/share/vm/classfile/verifier.hpp	Thu Nov 06 04:57:28 2014 -0800
+++ b/src/share/vm/classfile/verifier.hpp	Mon Jan 19 05:28:21 2015 +0000
@@ -97,9 +97,6 @@
   size_t _message_buffer_len;
   GrowableArray<Symbol*>* _symbols;  // keep a list of symbols created
 
-  // Used to detect illegal jumps over calls to super() nd this() in ctors.
-  int32_t _furthest_jump;
-
   void verify_method(methodHandle method, TRAPS);
   char* generate_code_data(methodHandle m, u4 code_length, TRAPS);
   void verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS);
@@ -236,18 +233,6 @@
 
   static bool _verify_verbose;  // for debugging
 
-  // Keep track of the furthest branch done in a method to make sure that
-  // there are no branches over calls to super() or this() from inside of
-  // a constructor.
-  int32_t furthest_jump() { return _furthest_jump; }
-
-  void set_furthest_jump(int32_t target) {
-    _furthest_jump = target;
-  }
-
-  void update_furthest_jump(int32_t target) {
-    if (target > _furthest_jump) _furthest_jump = target;
-  }
 };
 
 inline int ClassVerifier::change_sig_to_verificationType(