Tue, 12 Aug 2014 20:29:25 -0400
8050485: super() in a try block in a ctor causes VerifyError
Summary: Parse catch clause paths to ensure they end in throws
Reviewed-by: dlong, acorn, kamg, ctornqvi, lfoltan
src/share/vm/classfile/verifier.cpp | file | annotate | diff | comparison | revisions | |
src/share/vm/classfile/verifier.hpp | file | annotate | diff | comparison | revisions |
1.1 --- a/src/share/vm/classfile/verifier.cpp Wed Aug 20 15:32:00 2014 -0700 1.2 +++ b/src/share/vm/classfile/verifier.cpp Tue Aug 12 20:29:25 2014 -0400 1.3 @@ -2231,6 +2231,181 @@ 1.4 } 1.5 } 1.6 1.7 +// Look at the method's handlers. If the bci is in the handler's try block 1.8 +// then check if the handler_pc is already on the stack. If not, push it. 1.9 +void ClassVerifier::push_handlers(ExceptionTable* exhandlers, 1.10 + GrowableArray<u4>* handler_stack, 1.11 + u4 bci) { 1.12 + int exlength = exhandlers->length(); 1.13 + for(int x = 0; x < exlength; x++) { 1.14 + if (bci >= exhandlers->start_pc(x) && bci < exhandlers->end_pc(x)) { 1.15 + handler_stack->append_if_missing(exhandlers->handler_pc(x)); 1.16 + } 1.17 + } 1.18 +} 1.19 + 1.20 +// Return TRUE if all code paths starting with start_bc_offset end in 1.21 +// bytecode athrow or loop. 1.22 +bool ClassVerifier::ends_in_athrow(u4 start_bc_offset) { 1.23 + ResourceMark rm; 1.24 + // Create bytecode stream. 1.25 + RawBytecodeStream bcs(method()); 1.26 + u4 code_length = method()->code_size(); 1.27 + bcs.set_start(start_bc_offset); 1.28 + u4 target; 1.29 + // Create stack for storing bytecode start offsets for if* and *switch. 1.30 + GrowableArray<u4>* bci_stack = new GrowableArray<u4>(30); 1.31 + // Create stack for handlers for try blocks containing this handler. 1.32 + GrowableArray<u4>* handler_stack = new GrowableArray<u4>(30); 1.33 + // Create list of visited branch opcodes (goto* and if*). 1.34 + GrowableArray<u4>* visited_branches = new GrowableArray<u4>(30); 1.35 + ExceptionTable exhandlers(_method()); 1.36 + 1.37 + while (true) { 1.38 + if (bcs.is_last_bytecode()) { 1.39 + // if no more starting offsets to parse or if at the end of the 1.40 + // method then return false. 1.41 + if ((bci_stack->is_empty()) || ((u4)bcs.end_bci() == code_length)) 1.42 + return false; 1.43 + // Pop a bytecode starting offset and scan from there. 1.44 + bcs.set_start(bci_stack->pop()); 1.45 + } 1.46 + Bytecodes::Code opcode = bcs.raw_next(); 1.47 + u4 bci = bcs.bci(); 1.48 + 1.49 + // If the bytecode is in a TRY block, push its handlers so they 1.50 + // will get parsed. 1.51 + push_handlers(&exhandlers, handler_stack, bci); 1.52 + 1.53 + switch (opcode) { 1.54 + case Bytecodes::_if_icmpeq: 1.55 + case Bytecodes::_if_icmpne: 1.56 + case Bytecodes::_if_icmplt: 1.57 + case Bytecodes::_if_icmpge: 1.58 + case Bytecodes::_if_icmpgt: 1.59 + case Bytecodes::_if_icmple: 1.60 + case Bytecodes::_ifeq: 1.61 + case Bytecodes::_ifne: 1.62 + case Bytecodes::_iflt: 1.63 + case Bytecodes::_ifge: 1.64 + case Bytecodes::_ifgt: 1.65 + case Bytecodes::_ifle: 1.66 + case Bytecodes::_if_acmpeq: 1.67 + case Bytecodes::_if_acmpne: 1.68 + case Bytecodes::_ifnull: 1.69 + case Bytecodes::_ifnonnull: 1.70 + target = bcs.dest(); 1.71 + if (visited_branches->contains(bci)) { 1.72 + if (bci_stack->is_empty()) return true; 1.73 + // Pop a bytecode starting offset and scan from there. 1.74 + bcs.set_start(bci_stack->pop()); 1.75 + } else { 1.76 + if (target > bci) { // forward branch 1.77 + if (target >= code_length) return false; 1.78 + // Push the branch target onto the stack. 1.79 + bci_stack->push(target); 1.80 + // then, scan bytecodes starting with next. 1.81 + bcs.set_start(bcs.next_bci()); 1.82 + } else { // backward branch 1.83 + // Push bytecode offset following backward branch onto the stack. 1.84 + bci_stack->push(bcs.next_bci()); 1.85 + // Check bytecodes starting with branch target. 1.86 + bcs.set_start(target); 1.87 + } 1.88 + // Record target so we don't branch here again. 1.89 + visited_branches->append(bci); 1.90 + } 1.91 + break; 1.92 + 1.93 + case Bytecodes::_goto: 1.94 + case Bytecodes::_goto_w: 1.95 + target = (opcode == Bytecodes::_goto ? bcs.dest() : bcs.dest_w()); 1.96 + if (visited_branches->contains(bci)) { 1.97 + if (bci_stack->is_empty()) return true; 1.98 + // Been here before, pop new starting offset from stack. 1.99 + bcs.set_start(bci_stack->pop()); 1.100 + } else { 1.101 + if (target >= code_length) return false; 1.102 + // Continue scanning from the target onward. 1.103 + bcs.set_start(target); 1.104 + // Record target so we don't branch here again. 1.105 + visited_branches->append(bci); 1.106 + } 1.107 + break; 1.108 + 1.109 + // Check that all switch alternatives end in 'athrow' bytecodes. Since it 1.110 + // is difficult to determine where each switch alternative ends, parse 1.111 + // each switch alternative until either hit a 'return', 'athrow', or reach 1.112 + // the end of the method's bytecodes. This is gross but should be okay 1.113 + // because: 1.114 + // 1. tableswitch and lookupswitch byte codes in handlers for ctor explicit 1.115 + // constructor invocations should be rare. 1.116 + // 2. if each switch alternative ends in an athrow then the parsing should be 1.117 + // short. If there is no athrow then it is bogus code, anyway. 1.118 + case Bytecodes::_lookupswitch: 1.119 + case Bytecodes::_tableswitch: 1.120 + { 1.121 + address aligned_bcp = (address) round_to((intptr_t)(bcs.bcp() + 1), jintSize); 1.122 + u4 default_offset = Bytes::get_Java_u4(aligned_bcp) + bci; 1.123 + int keys, delta; 1.124 + if (opcode == Bytecodes::_tableswitch) { 1.125 + jint low = (jint)Bytes::get_Java_u4(aligned_bcp + jintSize); 1.126 + jint high = (jint)Bytes::get_Java_u4(aligned_bcp + 2*jintSize); 1.127 + // This is invalid, but let the regular bytecode verifier 1.128 + // report this because the user will get a better error message. 1.129 + if (low > high) return true; 1.130 + keys = high - low + 1; 1.131 + delta = 1; 1.132 + } else { 1.133 + keys = (int)Bytes::get_Java_u4(aligned_bcp + jintSize); 1.134 + delta = 2; 1.135 + } 1.136 + // Invalid, let the regular bytecode verifier deal with it. 1.137 + if (keys < 0) return true; 1.138 + 1.139 + // Push the offset of the next bytecode onto the stack. 1.140 + bci_stack->push(bcs.next_bci()); 1.141 + 1.142 + // Push the switch alternatives onto the stack. 1.143 + for (int i = 0; i < keys; i++) { 1.144 + u4 target = bci + (jint)Bytes::get_Java_u4(aligned_bcp+(3+i*delta)*jintSize); 1.145 + if (target > code_length) return false; 1.146 + bci_stack->push(target); 1.147 + } 1.148 + 1.149 + // Start bytecode parsing for the switch at the default alternative. 1.150 + if (default_offset > code_length) return false; 1.151 + bcs.set_start(default_offset); 1.152 + break; 1.153 + } 1.154 + 1.155 + case Bytecodes::_return: 1.156 + return false; 1.157 + 1.158 + case Bytecodes::_athrow: 1.159 + { 1.160 + if (bci_stack->is_empty()) { 1.161 + if (handler_stack->is_empty()) { 1.162 + return true; 1.163 + } else { 1.164 + // Parse the catch handlers for try blocks containing athrow. 1.165 + bcs.set_start(handler_stack->pop()); 1.166 + } 1.167 + } else { 1.168 + // Pop a bytecode offset and starting scanning from there. 1.169 + bcs.set_start(bci_stack->pop()); 1.170 + } 1.171 + } 1.172 + break; 1.173 + 1.174 + default: 1.175 + ; 1.176 + } // end switch 1.177 + } // end while loop 1.178 + 1.179 + return false; 1.180 +} 1.181 + 1.182 void ClassVerifier::verify_invoke_init( 1.183 RawBytecodeStream* bcs, u2 ref_class_index, VerificationType ref_class_type, 1.184 StackMapFrame* current_frame, u4 code_length, bool *this_uninit, 1.185 @@ -2250,18 +2425,26 @@ 1.186 return; 1.187 } 1.188 1.189 - // Make sure that this call is not done from within a TRY block because 1.190 - // that can result in returning an incomplete object. Simply checking 1.191 - // (bci >= start_pc) also ensures that this call is not done after a TRY 1.192 - // block. That is also illegal because this call must be the first Java 1.193 - // statement in the constructor. 1.194 + // Check if this call is done from inside of a TRY block. If so, make 1.195 + // sure that all catch clause paths end in a throw. Otherwise, this 1.196 + // can result in returning an incomplete object. 1.197 ExceptionTable exhandlers(_method()); 1.198 int exlength = exhandlers.length(); 1.199 for(int i = 0; i < exlength; i++) { 1.200 - if (bci >= exhandlers.start_pc(i)) { 1.201 - verify_error(ErrorContext::bad_code(bci), 1.202 - "Bad <init> method call from after the start of a try block"); 1.203 - return; 1.204 + u2 start_pc = exhandlers.start_pc(i); 1.205 + u2 end_pc = exhandlers.end_pc(i); 1.206 + 1.207 + if (bci >= start_pc && bci < end_pc) { 1.208 + if (!ends_in_athrow(exhandlers.handler_pc(i))) { 1.209 + verify_error(ErrorContext::bad_code(bci), 1.210 + "Bad <init> method call from after the start of a try block"); 1.211 + return; 1.212 + } else if (VerboseVerification) { 1.213 + ResourceMark rm; 1.214 + tty->print_cr( 1.215 + "Survived call to ends_in_athrow(): %s", 1.216 + current_class()->name()->as_C_string()); 1.217 + } 1.218 } 1.219 } 1.220
2.1 --- a/src/share/vm/classfile/verifier.hpp Wed Aug 20 15:32:00 2014 -0700 2.2 +++ b/src/share/vm/classfile/verifier.hpp Tue Aug 12 20:29:25 2014 -0400 2.3 @@ -30,6 +30,7 @@ 2.4 #include "oops/klass.hpp" 2.5 #include "oops/method.hpp" 2.6 #include "runtime/handles.hpp" 2.7 +#include "utilities/growableArray.hpp" 2.8 #include "utilities/exceptions.hpp" 2.9 2.10 // The verifier class 2.11 @@ -303,6 +304,16 @@ 2.12 StackMapFrame* current_frame, u4 code_length, bool* this_uninit, 2.13 constantPoolHandle cp, TRAPS); 2.14 2.15 + // Used by ends_in_athrow() to push all handlers that contain bci onto 2.16 + // the handler_stack, if the handler is not already on the stack. 2.17 + void push_handlers(ExceptionTable* exhandlers, 2.18 + GrowableArray<u4>* handler_stack, 2.19 + u4 bci); 2.20 + 2.21 + // Returns true if all paths starting with start_bc_offset end in athrow 2.22 + // bytecode or loop. 2.23 + bool ends_in_athrow(u4 start_bc_offset); 2.24 + 2.25 void verify_invoke_instructions( 2.26 RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame, 2.27 bool* this_uninit, VerificationType return_type,