< prev index next >

src/hotspot/share/classfile/stackMapTable.cpp

Print this page
@@ -125,10 +125,11 @@
      frame->set_locals_size(lsize);
      frame->copy_locals(stackmap_frame);
      frame->set_stack_size(ssize);
      frame->copy_stack(stackmap_frame);
      frame->set_flags(stackmap_frame->flags());
+     frame->set_assert_unset_fields(stackmap_frame->assert_unset_fields());
    }
    return result;
  }
  
  void StackMapTable::check_jump_target(

@@ -155,15 +156,17 @@
  }
  
  StackMapReader::StackMapReader(ClassVerifier* v, StackMapStream* stream,
                                 char* code_data, int32_t code_len,
                                 StackMapFrame* init_frame,
-                                u2 max_locals, u2 max_stack, TRAPS) :
+                                u2 max_locals, u2 max_stack,
+                                StackMapFrame::AssertUnsetFieldTable* initial_strict_fields, TRAPS) :
                                    _verifier(v), _stream(stream), _code_data(code_data),
                                    _code_length(code_len), _parsed_frame_count(0),
                                    _prev_frame(init_frame), _max_locals(max_locals),
-                                   _max_stack(max_stack), _first(true) {
+                                   _max_stack(max_stack), _assert_unset_fields_buffer(initial_strict_fields),
+                                   _first(true) {
    methodHandle m = v->method();
    if (m->has_stackmap_table()) {
      _cp = constantPoolHandle(THREAD, m->constants());
      _frame_count = _stream->get_u2(CHECK);
    } else {

@@ -201,11 +204,12 @@
          (!_cp->tag_at(class_index).is_klass() &&
           !_cp->tag_at(class_index).is_unresolved_klass())) {
        _stream->stackmap_format_error("bad class index", THREAD);
        return VerificationType::bogus_type();
      }
-     return VerificationType::reference_type(_cp->klass_name_at(class_index));
+     Symbol* klass_name = _cp->klass_name_at(class_index);
+     return VerificationType::reference_type(klass_name);
    }
    if (tag == ITEM_UninitializedThis) {
      if (flags != nullptr) {
        *flags |= FLAG_THIS_UNINIT;
      }

@@ -242,10 +246,43 @@
  StackMapFrame* StackMapReader::next_helper(TRAPS) {
    StackMapFrame* frame;
    int offset;
    VerificationType* locals = nullptr;
    u1 frame_type = _stream->get_u1(CHECK_NULL);
+   if (frame_type == ASSERT_UNSET_FIELDS) {
+     u2 num_unset_fields = _stream->get_u2(CHECK_NULL);
+     StackMapFrame::AssertUnsetFieldTable* new_fields = new StackMapFrame::AssertUnsetFieldTable();
+ 
+     for (u2 i = 0; i < num_unset_fields; i++) {
+       u2 index = _stream->get_u2(CHECK_NULL);
+       Symbol* name = _cp->symbol_at(_cp->name_ref_index_at(index));
+       Symbol* sig = _cp->symbol_at(_cp->signature_ref_index_at(index));
+       NameAndSig tmp(name, sig);
+ 
+       if (!_prev_frame->assert_unset_fields()->contains(tmp)) {
+         ResourceMark rm(THREAD);
+         log_info(verification)("Field %s%s is not found among initial strict instance fields", name->as_C_string(), sig->as_C_string());
+         StackMapFrame::print_strict_fields(_prev_frame->assert_unset_fields());
+         _prev_frame->verifier()->verify_error(
+             ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame),
+             "Strict fields not a subset of initial strict instance fields: %s:%s", name->as_C_string(), sig->as_C_string());
+       } else {
+         new_fields->put(tmp, false);
+       }
+     }
+ 
+     // Only modify strict instance fields the frame has uninitialized this
+     if (_prev_frame->flag_this_uninit()) {
+       _assert_unset_fields_buffer = _prev_frame->merge_unset_fields(new_fields);
+     } else if (new_fields->number_of_entries() > 0) {
+       _prev_frame->verifier()->verify_error(
+         ErrorContext::bad_strict_fields(_prev_frame->offset(), _prev_frame),
+         "Cannot have uninitialized strict fields after class initialization");
+     }
+ 
+     return nullptr;
+   }
    if (frame_type < 64) {
      // same_frame
      if (_first) {
        offset = frame_type;
        // Can't share the locals array since that is updated by the verifier.

@@ -257,11 +294,12 @@
        offset = _prev_frame->offset() + frame_type + 1;
        locals = _prev_frame->locals();
      }
      frame = new StackMapFrame(
        offset, _prev_frame->flags(), _prev_frame->locals_size(), 0,
-       _max_locals, _max_stack, locals, nullptr, _verifier);
+       _max_locals, _max_stack, locals, nullptr,
+       _assert_unset_fields_buffer, _verifier);
      if (_first && locals != nullptr) {
        frame->copy_locals(_prev_frame);
      }
      _first = false;
      return frame;

@@ -289,21 +327,22 @@
      }
      check_verification_type_array_size(
        stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr));
      frame = new StackMapFrame(
        offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size,
-       _max_locals, _max_stack, locals, stack, _verifier);
+       _max_locals, _max_stack, locals, stack,
+       _assert_unset_fields_buffer, _verifier);
      if (_first && locals != nullptr) {
        frame->copy_locals(_prev_frame);
      }
      _first = false;
      return frame;
    }
  
    u2 offset_delta = _stream->get_u2(CHECK_NULL);
  
-   if (frame_type < SAME_LOCALS_1_STACK_ITEM_EXTENDED) {
+   if (frame_type < ASSERT_UNSET_FIELDS) {
      // reserved frame types
      _stream->stackmap_format_error(
        "reserved frame type", CHECK_VERIFY_(_verifier, nullptr));
    }
  

@@ -330,11 +369,12 @@
      }
      check_verification_type_array_size(
        stack_size, _max_stack, CHECK_VERIFY_(_verifier, nullptr));
      frame = new StackMapFrame(
        offset, _prev_frame->flags(), _prev_frame->locals_size(), stack_size,
-       _max_locals, _max_stack, locals, stack, _verifier);
+       _max_locals, _max_stack, locals, stack,
+       _assert_unset_fields_buffer, _verifier);
      if (_first && locals != nullptr) {
        frame->copy_locals(_prev_frame);
      }
      _first = false;
      return frame;

@@ -372,11 +412,12 @@
      } else {
        offset = _prev_frame->offset() + offset_delta + 1;
      }
      frame = new StackMapFrame(
        offset, flags, new_length, 0, _max_locals, _max_stack,
-       locals, nullptr, _verifier);
+       locals, nullptr,
+       _assert_unset_fields_buffer, _verifier);
      if (_first && locals != nullptr) {
        frame->copy_locals(_prev_frame);
      }
      _first = false;
      return frame;

@@ -406,11 +447,12 @@
      } else {
        offset = _prev_frame->offset() + offset_delta + 1;
      }
      frame = new StackMapFrame(
        offset, flags, real_length, 0, _max_locals,
-       _max_stack, locals, nullptr, _verifier);
+       _max_stack, locals, nullptr,
+       _assert_unset_fields_buffer, _verifier);
      _first = false;
      return frame;
    }
    if (frame_type == FULL) {
      // full_frame

@@ -454,11 +496,12 @@
      } else {
        offset = _prev_frame->offset() + offset_delta + 1;
      }
      frame = new StackMapFrame(
        offset, flags, real_locals_size, real_stack_size,
-       _max_locals, _max_stack, locals, stack, _verifier);
+       _max_locals, _max_stack, locals, stack,
+       _assert_unset_fields_buffer, _verifier);
      _first = false;
      return frame;
    }
  
    _stream->stackmap_format_error(
< prev index next >