Sat, 02 Aug 2014 16:28:59 -0400
8051012: Regression in verifier for <init> method call from inside of a branch
Summary: Fix stackmap matching for branches.
Reviewed-by: coleenp, lfoltan, acorn
1.1 --- a/src/share/vm/classfile/stackMapTable.cpp Thu Jan 16 13:25:25 2014 -0800 1.2 +++ b/src/share/vm/classfile/stackMapTable.cpp Sat Aug 02 16:28:59 2014 -0400 1.3 @@ -70,24 +70,26 @@ 1.4 1.5 bool StackMapTable::match_stackmap( 1.6 StackMapFrame* frame, int32_t target, 1.7 - bool match, bool update, ErrorContext* ctx, TRAPS) const { 1.8 + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { 1.9 int index = get_index_from_offset(target); 1.10 - return match_stackmap(frame, target, index, match, update, ctx, THREAD); 1.11 + return match_stackmap(frame, target, index, match, update, handler, ctx, THREAD); 1.12 } 1.13 1.14 // Match and/or update current_frame to the frame in stackmap table with 1.15 // specified offset and frame index. Return true if the two frames match. 1.16 +// handler is true if the frame in stackmap_table is for an exception handler. 1.17 // 1.18 -// The values of match and update are: _match__update_ 1.19 +// The values of match and update are: _match__update__handler 1.20 // 1.21 -// checking a branch target/exception handler: true false 1.22 +// checking a branch target: true false false 1.23 +// checking an exception handler: true false true 1.24 // linear bytecode verification following an 1.25 -// unconditional branch: false true 1.26 +// unconditional branch: false true false 1.27 // linear bytecode verification not following an 1.28 -// unconditional branch: true true 1.29 +// unconditional branch: true true false 1.30 bool StackMapTable::match_stackmap( 1.31 StackMapFrame* frame, int32_t target, int32_t frame_index, 1.32 - bool match, bool update, ErrorContext* ctx, TRAPS) const { 1.33 + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const { 1.34 if (frame_index < 0 || frame_index >= _frame_count) { 1.35 *ctx = ErrorContext::missing_stackmap(frame->offset()); 1.36 frame->verifier()->verify_error( 1.37 @@ -98,11 +100,9 @@ 1.38 StackMapFrame *stackmap_frame = _frame_array[frame_index]; 1.39 bool result = true; 1.40 if (match) { 1.41 - // when checking handler target, match == true && update == false 1.42 - bool is_exception_handler = !update; 1.43 // Has direct control flow from last instruction, need to match the two 1.44 // frames. 1.45 - result = frame->is_assignable_to(stackmap_frame, is_exception_handler, 1.46 + result = frame->is_assignable_to(stackmap_frame, handler, 1.47 ctx, CHECK_VERIFY_(frame->verifier(), result)); 1.48 } 1.49 if (update) { 1.50 @@ -126,7 +126,7 @@ 1.51 StackMapFrame* frame, int32_t target, TRAPS) const { 1.52 ErrorContext ctx; 1.53 bool match = match_stackmap( 1.54 - frame, target, true, false, &ctx, CHECK_VERIFY(frame->verifier())); 1.55 + frame, target, true, false, false, &ctx, CHECK_VERIFY(frame->verifier())); 1.56 if (!match || (target < 0 || target >= _code_length)) { 1.57 frame->verifier()->verify_error(ctx, 1.58 "Inconsistent stackmap frames at branch target %d", target); 1.59 @@ -134,7 +134,6 @@ 1.60 } 1.61 // check if uninitialized objects exist on backward branches 1.62 check_new_object(frame, target, CHECK_VERIFY(frame->verifier())); 1.63 - frame->verifier()->update_furthest_jump(target); 1.64 } 1.65 1.66 void StackMapTable::check_new_object(
2.1 --- a/src/share/vm/classfile/stackMapTable.hpp Thu Jan 16 13:25:25 2014 -0800 2.2 +++ b/src/share/vm/classfile/stackMapTable.hpp Sat Aug 02 16:28:59 2014 -0400 2.3 @@ -74,12 +74,12 @@ 2.4 // specified offset. Return true if the two frames match. 2.5 bool match_stackmap( 2.6 StackMapFrame* current_frame, int32_t offset, 2.7 - bool match, bool update, ErrorContext* ctx, TRAPS) const; 2.8 + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const; 2.9 // Match and/or update current_frame to the frame in stackmap table with 2.10 // specified offset and frame index. Return true if the two frames match. 2.11 bool match_stackmap( 2.12 StackMapFrame* current_frame, int32_t offset, int32_t frame_index, 2.13 - bool match, bool update, ErrorContext* ctx, TRAPS) const; 2.14 + bool match, bool update, bool handler, ErrorContext* ctx, TRAPS) const; 2.15 2.16 // Check jump instructions. Make sure there are no uninitialized 2.17 // instances on backward branch.
3.1 --- a/src/share/vm/classfile/verifier.cpp Thu Jan 16 13:25:25 2014 -0800 3.2 +++ b/src/share/vm/classfile/verifier.cpp Sat Aug 02 16:28:59 2014 -0400 3.3 @@ -634,8 +634,6 @@ 3.4 // flow from current instruction to the next 3.5 // instruction in sequence 3.6 3.7 - set_furthest_jump(0); 3.8 - 3.9 Bytecodes::Code opcode; 3.10 while (!bcs.is_last_bytecode()) { 3.11 // Check for recursive re-verification before each bytecode. 3.12 @@ -1794,7 +1792,7 @@ 3.13 // If matched, current_frame will be updated by this method. 3.14 bool matches = stackmap_table->match_stackmap( 3.15 current_frame, this_offset, stackmap_index, 3.16 - !no_control_flow, true, &ctx, CHECK_VERIFY_(this, 0)); 3.17 + !no_control_flow, true, false, &ctx, CHECK_VERIFY_(this, 0)); 3.18 if (!matches) { 3.19 // report type error 3.20 verify_error(ctx, "Instruction type does not match stack map"); 3.21 @@ -1841,7 +1839,7 @@ 3.22 } 3.23 ErrorContext ctx; 3.24 bool matches = stackmap_table->match_stackmap( 3.25 - new_frame, handler_pc, true, false, &ctx, CHECK_VERIFY(this)); 3.26 + new_frame, handler_pc, true, false, true, &ctx, CHECK_VERIFY(this)); 3.27 if (!matches) { 3.28 verify_error(ctx, "Stack map does not match the one at " 3.29 "exception handler %d", handler_pc); 3.30 @@ -2252,13 +2250,6 @@ 3.31 return; 3.32 } 3.33 3.34 - // Make sure that this call is not jumped over. 3.35 - if (bci < furthest_jump()) { 3.36 - verify_error(ErrorContext::bad_code(bci), 3.37 - "Bad <init> method call from inside of a branch"); 3.38 - return; 3.39 - } 3.40 - 3.41 // Make sure that this call is not done from within a TRY block because 3.42 // that can result in returning an incomplete object. Simply checking 3.43 // (bci >= start_pc) also ensures that this call is not done after a TRY
4.1 --- a/src/share/vm/classfile/verifier.hpp Thu Jan 16 13:25:25 2014 -0800 4.2 +++ b/src/share/vm/classfile/verifier.hpp Sat Aug 02 16:28:59 2014 -0400 4.3 @@ -258,9 +258,6 @@ 4.4 4.5 ErrorContext _error_context; // contains information about an error 4.6 4.7 - // Used to detect illegal jumps over calls to super() nd this() in ctors. 4.8 - int32_t _furthest_jump; 4.9 - 4.10 void verify_method(methodHandle method, TRAPS); 4.11 char* generate_code_data(methodHandle m, u4 code_length, TRAPS); 4.12 void verify_exception_handler_table(u4 code_length, char* code_data, 4.13 @@ -407,19 +404,6 @@ 4.14 4.15 TypeOrigin ref_ctx(const char* str, TRAPS); 4.16 4.17 - // Keep track of the furthest branch done in a method to make sure that 4.18 - // there are no branches over calls to super() or this() from inside of 4.19 - // a constructor. 4.20 - int32_t furthest_jump() { return _furthest_jump; } 4.21 - 4.22 - void set_furthest_jump(int32_t target) { 4.23 - _furthest_jump = target; 4.24 - } 4.25 - 4.26 - void update_furthest_jump(int32_t target) { 4.27 - if (target > _furthest_jump) _furthest_jump = target; 4.28 - } 4.29 - 4.30 }; 4.31 4.32 inline int ClassVerifier::change_sig_to_verificationType(