diff src/share/vm/classfile/verifier.cpp @ 17573:aff11567504c

8035119: Fix exceptions to bytecode verification Summary: Prevent ctor calls to super() and this() from avoidable code (try blocks, if stmts, etc.) Reviewed-by: coleenp, acorn, mschoene
author hseigel
date Mon, 17 Mar 2014 10:17:55 -0400
parents 22eaa15b7960
children b5ae226b7516
line wrap: on
line diff
--- a/src/share/vm/classfile/verifier.cpp	Tue Mar 11 14:02:23 2014 -0700
+++ b/src/share/vm/classfile/verifier.cpp	Mon Mar 17 10:17:55 2014 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 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
@@ -632,6 +632,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.
@@ -2245,6 +2248,29 @@
           "Bad <init> method call");
       return;
     }
+
+    // Make sure that this call is not jumped over.
+    if (bci < furthest_jump()) {
+      verify_error(ErrorContext::bad_code(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.
+    ExceptionTable exhandlers(_method());
+    int exlength = exhandlers.length();
+    for(int i = 0; i < exlength; i++) {
+      if (bci >= exhandlers.start_pc(i)) {
+        verify_error(ErrorContext::bad_code(bci),
+                     "Bad <init> method call from after the start of a try block");
+        return;
+      }
+    }
+
     current_frame->initialize_object(type, current_type());
     *this_uninit = true;
   } else if (type.is_uninitialized()) {