changeset 8575:279a5dd96f9b

8175340: Possible invalid memory accesses due to ciMethodData::bci_to_data() returning NULL Summary: Check values returned by ciMethodData::bci_to_data() where necessary. Reviewed-by: kvn
author zmajo
date Thu, 09 Mar 2017 14:27:21 +0100
parents c7f6875cc8c3
children aa4ffb1f30c9
files src/share/vm/c1/c1_GraphBuilder.cpp src/share/vm/c1/c1_LIRGenerator.cpp src/share/vm/ci/ciMethodData.cpp src/share/vm/opto/parse2.cpp
diffstat 4 files changed, 87 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Jul 25 15:30:54 2017 +0000
+++ b/src/share/vm/c1/c1_GraphBuilder.cpp	Thu Mar 09 14:27:21 2017 +0100
@@ -1530,7 +1530,7 @@
         ciMethod* caller = state()->scope()->method();
         ciMethodData* md = caller->method_data_or_null();
         ciProfileData* data = md->bci_to_data(invoke_bci);
-        if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) {
+        if (data != NULL && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
           bool has_return = data->is_CallTypeData() ? ((ciCallTypeData*)data)->has_return() : ((ciVirtualCallTypeData*)data)->has_return();
           // May not be true in case of an inlined call through a method handle intrinsic.
           if (has_return) {
@@ -1747,7 +1747,7 @@
   start = has_receiver ? 1 : 0;
   if (profile_arguments()) {
     ciProfileData* data = method()->method_data()->bci_to_data(bci());
-    if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) {
+    if (data != NULL && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
       n = data->is_CallTypeData() ? data->as_CallTypeData()->number_of_arguments() : data->as_VirtualCallTypeData()->number_of_arguments();
     }
   }
@@ -4465,7 +4465,7 @@
   }
   ciMethodData* md = m->method_data_or_null();
   ciProfileData* data = md->bci_to_data(invoke_bci);
-  if (data->is_CallTypeData() || data->is_VirtualCallTypeData()) {
+  if (data != NULL && (data->is_CallTypeData() || data->is_VirtualCallTypeData())) {
     append(new ProfileReturnType(m , invoke_bci, callee, ret));
   }
 }
--- a/src/share/vm/c1/c1_LIRGenerator.cpp	Tue Jul 25 15:30:54 2017 +0000
+++ b/src/share/vm/c1/c1_LIRGenerator.cpp	Thu Mar 09 14:27:21 2017 +0100
@@ -3185,50 +3185,52 @@
     int bci = x->bci_of_invoke();
     ciMethodData* md = x->method()->method_data_or_null();
     ciProfileData* data = md->bci_to_data(bci);
-    if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) ||
-        (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) {
-      ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset();
-      int base_offset = md->byte_offset_of_slot(data, extra);
-      LIR_Opr mdp = LIR_OprFact::illegalOpr;
-      ciTypeStackSlotEntries* args = data->is_CallTypeData() ? ((ciCallTypeData*)data)->args() : ((ciVirtualCallTypeData*)data)->args();
-
-      Bytecodes::Code bc = x->method()->java_code_at_bci(bci);
-      int start = 0;
-      int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments();
-      if (x->callee()->is_loaded() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) {
-        // first argument is not profiled at call (method handle invoke)
-        assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected");
-        start = 1;
+    if (data != NULL) {
+      if ((data->is_CallTypeData() && data->as_CallTypeData()->has_arguments()) ||
+          (data->is_VirtualCallTypeData() && data->as_VirtualCallTypeData()->has_arguments())) {
+        ByteSize extra = data->is_CallTypeData() ? CallTypeData::args_data_offset() : VirtualCallTypeData::args_data_offset();
+        int base_offset = md->byte_offset_of_slot(data, extra);
+        LIR_Opr mdp = LIR_OprFact::illegalOpr;
+        ciTypeStackSlotEntries* args = data->is_CallTypeData() ? ((ciCallTypeData*)data)->args() : ((ciVirtualCallTypeData*)data)->args();
+
+        Bytecodes::Code bc = x->method()->java_code_at_bci(bci);
+        int start = 0;
+        int stop = data->is_CallTypeData() ? ((ciCallTypeData*)data)->number_of_arguments() : ((ciVirtualCallTypeData*)data)->number_of_arguments();
+        if (x->callee()->is_loaded() && x->callee()->is_static() && Bytecodes::has_receiver(bc)) {
+          // first argument is not profiled at call (method handle invoke)
+          assert(x->method()->raw_code_at_bci(bci) == Bytecodes::_invokehandle, "invokehandle expected");
+          start = 1;
+        }
+        ciSignature* callee_signature = x->callee()->signature();
+        // method handle call to virtual method
+        bool has_receiver = x->callee()->is_loaded() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc);
+        ciSignatureStream callee_signature_stream(callee_signature, has_receiver ? x->callee()->holder() : NULL);
+
+        bool ignored_will_link;
+        ciSignature* signature_at_call = NULL;
+        x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
+        ciSignatureStream signature_at_call_stream(signature_at_call);
+
+        // if called through method handle invoke, some arguments may have been popped
+        for (int i = 0; i < stop && i+start < x->nb_profiled_args(); i++) {
+          int off = in_bytes(TypeEntriesAtCall::argument_type_offset(i)) - in_bytes(TypeEntriesAtCall::args_data_offset());
+          ciKlass* exact = profile_type(md, base_offset, off,
+              args->type(i), x->profiled_arg_at(i+start), mdp,
+              !x->arg_needs_null_check(i+start),
+              signature_at_call_stream.next_klass(), callee_signature_stream.next_klass());
+          if (exact != NULL) {
+            md->set_argument_type(bci, i, exact);
+          }
+        }
+      } else {
+#ifdef ASSERT
+        Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke());
+        int n = x->nb_profiled_args();
+        assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() ||
+            (x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))),
+            "only at JSR292 bytecodes");
+#endif
       }
-      ciSignature* callee_signature = x->callee()->signature();
-      // method handle call to virtual method
-      bool has_receiver = x->callee()->is_loaded() && !x->callee()->is_static() && !Bytecodes::has_receiver(bc);
-      ciSignatureStream callee_signature_stream(callee_signature, has_receiver ? x->callee()->holder() : NULL);
-
-      bool ignored_will_link;
-      ciSignature* signature_at_call = NULL;
-      x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
-      ciSignatureStream signature_at_call_stream(signature_at_call);
-
-      // if called through method handle invoke, some arguments may have been popped
-      for (int i = 0; i < stop && i+start < x->nb_profiled_args(); i++) {
-        int off = in_bytes(TypeEntriesAtCall::argument_type_offset(i)) - in_bytes(TypeEntriesAtCall::args_data_offset());
-        ciKlass* exact = profile_type(md, base_offset, off,
-                                      args->type(i), x->profiled_arg_at(i+start), mdp,
-                                      !x->arg_needs_null_check(i+start),
-                                      signature_at_call_stream.next_klass(), callee_signature_stream.next_klass());
-        if (exact != NULL) {
-          md->set_argument_type(bci, i, exact);
-        }
-      }
-    } else {
-#ifdef ASSERT
-      Bytecodes::Code code = x->method()->raw_code_at_bci(x->bci_of_invoke());
-      int n = x->nb_profiled_args();
-      assert(MethodData::profile_parameters() && (MethodData::profile_arguments_jsr292_only() ||
-                                                  (x->inlined() && ((code == Bytecodes::_invokedynamic && n <= 1) || (code == Bytecodes::_invokehandle && n <= 2)))),
-             "only at JSR292 bytecodes");
-#endif
     }
   }
 }
@@ -3319,24 +3321,26 @@
   int bci = x->bci_of_invoke();
   ciMethodData* md = x->method()->method_data_or_null();
   ciProfileData* data = md->bci_to_data(bci);
-  assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type");
-  ciReturnTypeEntry* ret = data->is_CallTypeData() ? ((ciCallTypeData*)data)->ret() : ((ciVirtualCallTypeData*)data)->ret();
-  LIR_Opr mdp = LIR_OprFact::illegalOpr;
-
-  bool ignored_will_link;
-  ciSignature* signature_at_call = NULL;
-  x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
-
-  // The offset within the MDO of the entry to update may be too large
-  // to be used in load/store instructions on some platforms. So have
-  // profile_type() compute the address of the profile in a register.
-  ciKlass* exact = profile_type(md, md->byte_offset_of_slot(data, ret->type_offset()), 0,
-                                ret->type(), x->ret(), mdp,
-                                !x->needs_null_check(),
-                                signature_at_call->return_type()->as_klass(),
-                                x->callee()->signature()->return_type()->as_klass());
-  if (exact != NULL) {
-    md->set_return_type(bci, exact);
+  if (data != NULL) {
+    assert(data->is_CallTypeData() || data->is_VirtualCallTypeData(), "wrong profile data type");
+    ciReturnTypeEntry* ret = data->is_CallTypeData() ? ((ciCallTypeData*)data)->ret() : ((ciVirtualCallTypeData*)data)->ret();
+    LIR_Opr mdp = LIR_OprFact::illegalOpr;
+
+    bool ignored_will_link;
+    ciSignature* signature_at_call = NULL;
+    x->method()->get_method_at_bci(bci, ignored_will_link, &signature_at_call);
+
+    // The offset within the MDO of the entry to update may be too large
+    // to be used in load/store instructions on some platforms. So have
+    // profile_type() compute the address of the profile in a register.
+    ciKlass* exact = profile_type(md, md->byte_offset_of_slot(data, ret->type_offset()), 0,
+        ret->type(), x->ret(), mdp,
+        !x->needs_null_check(),
+        signature_at_call->return_type()->as_klass(),
+        x->callee()->signature()->return_type()->as_klass());
+    if (exact != NULL) {
+      md->set_return_type(bci, exact);
+    }
   }
 }
 
--- a/src/share/vm/ci/ciMethodData.cpp	Tue Jul 25 15:30:54 2017 +0000
+++ b/src/share/vm/ci/ciMethodData.cpp	Thu Mar 09 14:27:21 2017 +0100
@@ -391,11 +391,13 @@
   MethodData* mdo = get_MethodData();
   if (mdo != NULL) {
     ProfileData* data = mdo->bci_to_data(bci);
-    if (data->is_CallTypeData()) {
-      data->as_CallTypeData()->set_argument_type(i, k->get_Klass());
-    } else {
-      assert(data->is_VirtualCallTypeData(), "no arguments!");
-      data->as_VirtualCallTypeData()->set_argument_type(i, k->get_Klass());
+    if (data != NULL) {
+      if (data->is_CallTypeData()) {
+        data->as_CallTypeData()->set_argument_type(i, k->get_Klass());
+      } else {
+        assert(data->is_VirtualCallTypeData(), "no arguments!");
+        data->as_VirtualCallTypeData()->set_argument_type(i, k->get_Klass());
+      }
     }
   }
 }
@@ -413,11 +415,13 @@
   MethodData* mdo = get_MethodData();
   if (mdo != NULL) {
     ProfileData* data = mdo->bci_to_data(bci);
-    if (data->is_CallTypeData()) {
-      data->as_CallTypeData()->set_return_type(k->get_Klass());
-    } else {
-      assert(data->is_VirtualCallTypeData(), "no arguments!");
-      data->as_VirtualCallTypeData()->set_return_type(k->get_Klass());
+    if (data != NULL) {
+      if (data->is_CallTypeData()) {
+        data->as_CallTypeData()->set_return_type(k->get_Klass());
+      } else {
+        assert(data->is_VirtualCallTypeData(), "no arguments!");
+        data->as_VirtualCallTypeData()->set_return_type(k->get_Klass());
+      }
     }
   }
 }
--- a/src/share/vm/opto/parse2.cpp	Tue Jul 25 15:30:54 2017 +0000
+++ b/src/share/vm/opto/parse2.cpp	Thu Mar 09 14:27:21 2017 +0100
@@ -812,6 +812,9 @@
     ciMethodData* methodData = method()->method_data();
     if (!methodData->is_mature())  return PROB_UNKNOWN;
     ciProfileData* data = methodData->bci_to_data(bci());
+    if (data == NULL) {
+      return PROB_UNKNOWN;
+    }
     if (!data->is_JumpData())  return PROB_UNKNOWN;
 
     // get taken and not taken values
@@ -903,8 +906,8 @@
         // of the OSR-ed method, and we want to deopt to gather more stats.
         // If you have ANY counts, then this loop is simply 'cold' relative
         // to the OSR loop.
-        if (data->as_BranchData()->taken() +
-            data->as_BranchData()->not_taken() == 0 ) {
+        if (data == NULL ||
+            (data->as_BranchData()->taken() +  data->as_BranchData()->not_taken() == 0)) {
           // This is the only way to return PROB_UNKNOWN:
           return PROB_UNKNOWN;
         }