changeset 4062:6177a94d77fd

8035119: Fix exceptions to bytecode verification Summary: Prevent ctor calls to super() and this() from avoidable code (try blocks, if stmts, etc.). Modified for openjdk6 hs23. Reviewed-by: hseigel, coleenp, acorn, mschoene
author chrisphi
date Sun, 06 Jul 2014 12:44:28 -0400
parents 1304e61f6271
children ce8ddc29d76d
files src/share/vm/classfile/stackMapTable.cpp src/share/vm/classfile/verifier.cpp src/share/vm/classfile/verifier.hpp
diffstat 3 files changed, 48 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/classfile/stackMapTable.cpp	Mon Apr 07 09:22:54 2014 -0400
+++ b/src/share/vm/classfile/stackMapTable.cpp	Sun Jul 06 12:44:28 2014 -0400
@@ -134,6 +134,7 @@
   }
   // 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/verifier.cpp	Mon Apr 07 09:22:54 2014 -0400
+++ b/src/share/vm/classfile/verifier.cpp	Sun Jul 06 12:44:28 2014 -0400
@@ -378,6 +378,9 @@
   bool no_control_flow = false; // Set to true when there is no direct control
                                 // 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.
@@ -1891,6 +1894,34 @@
       verify_error(bci, "Bad <init> method call");
       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
+    // block.  That is also illegal because this call must be the first Java
+    // statement in the constructor.
+    typeArrayHandle exhandlers (THREAD, _method->exception_table());
+    for(int i = 0; i < exhandlers->length(); i += 4) {
+      /*
+       * Skip reading end_pc, handler_pc and catch_type_index.
+       * Looks like this if you need all of them:
+       * u2 start_pc = exhandlers->int_at(i++);
+       * u2 end_pc = exhandlers->int_at(i++);
+       * u2 handler_pc = exhandlers->int_at(i++);
+       * int catch_type_index = exhandlers->int_at(i++);
+       */
+      u2 start_pc = exhandlers->int_at(i);
+      if (bci >= start_pc) {
+        verify_error(bci, "Bad <init> method call from after the start of a try block");
+      }
+    }
+
     current_frame->initialize_object(type, current_type());
     *this_uninit = true;
   } else if (type.is_uninitialized()) {
--- a/src/share/vm/classfile/verifier.hpp	Mon Apr 07 09:22:54 2014 -0400
+++ b/src/share/vm/classfile/verifier.hpp	Sun Jul 06 12:44:28 2014 -0400
@@ -97,6 +97,9 @@
   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);
@@ -232,6 +235,19 @@
   Symbol* create_temporary_symbol(const char *s, int length, TRAPS);
 
   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(