From 99f74d4a909c36a69c230a1132d7c15005af1314 Mon Sep 17 00:00:00 2001 From: zmajo Date: Thu, 9 Mar 2017 14:27:21 +0100 Subject: [PATCH] 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 --- src/share/vm/c1/c1_GraphBuilder.cpp | 6 +- src/share/vm/c1/c1_LIRGenerator.cpp | 122 ++++++++++++++-------------- src/share/vm/ci/ciMethodData.cpp | 24 +++--- src/share/vm/opto/parse2.cpp | 7 +- 4 files changed, 85 insertions(+), 74 deletions(-) diff --git a/src/share/vm/c1/c1_GraphBuilder.cpp b/src/share/vm/c1/c1_GraphBuilder.cpp index b6d4180c8..32185c65e 100644 --- a/src/share/vm/c1/c1_GraphBuilder.cpp +++ b/src/share/vm/c1/c1_GraphBuilder.cpp @@ -1530,7 +1530,7 @@ void GraphBuilder::method_return(Value x) { 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 @@ Values* GraphBuilder::args_list_for_profiling(ciMethod* target, int& start, bool 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 @@ void GraphBuilder::profile_return_type(Value ret, ciMethod* callee, ciMethod* m, } 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)); } } diff --git a/src/share/vm/c1/c1_LIRGenerator.cpp b/src/share/vm/c1/c1_LIRGenerator.cpp index 7d23f8c10..2a4373ba0 100644 --- a/src/share/vm/c1/c1_LIRGenerator.cpp +++ b/src/share/vm/c1/c1_LIRGenerator.cpp @@ -3185,50 +3185,52 @@ void LIRGenerator::profile_arguments(ProfileCall* x) { 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; - } - 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); + 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; } - } - } else { + 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"); + 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 @@ void LIRGenerator::do_ProfileReturnType(ProfileReturnType* x) { 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); + } } } diff --git a/src/share/vm/ci/ciMethodData.cpp b/src/share/vm/ci/ciMethodData.cpp index c57ec150d..a2d10796d 100644 --- a/src/share/vm/ci/ciMethodData.cpp +++ b/src/share/vm/ci/ciMethodData.cpp @@ -391,11 +391,13 @@ void ciMethodData::set_argument_type(int bci, int i, ciKlass* k) { 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 @@ void ciMethodData::set_return_type(int bci, ciKlass* k) { 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()); + } } } } diff --git a/src/share/vm/opto/parse2.cpp b/src/share/vm/opto/parse2.cpp index 8bdd5b54b..c4ce0e07d 100644 --- a/src/share/vm/opto/parse2.cpp +++ b/src/share/vm/opto/parse2.cpp @@ -812,6 +812,9 @@ float Parse::dynamic_branch_prediction(float &cnt, BoolTest::mask btest, Node* t 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 @@ float Parse::branch_prediction(float& cnt, // 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; } -- GitLab