8051012: Regression in verifier for <init> method call from inside of a branch

Sat, 02 Aug 2014 16:28:59 -0400

author
hseigel
date
Sat, 02 Aug 2014 16:28:59 -0400
changeset 6956
d14a18794c90
parent 6955
bcd72ab4d91f
child 6957
e0c6fadce66e
child 6958
d04cb4166be7

8051012: Regression in verifier for <init> method call from inside of a branch
Summary: Fix stackmap matching for branches.
Reviewed-by: coleenp, lfoltan, acorn

src/share/vm/classfile/stackMapTable.cpp file | annotate | diff | comparison | revisions
src/share/vm/classfile/stackMapTable.hpp file | annotate | diff | comparison | revisions
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/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(

mercurial