8259403: Zero: crash with NULL MethodHandle receiver

Reviewed-by: coleenp
This commit is contained in:
Aleksey Shipilev 2021-01-18 10:28:14 +00:00
parent e93f08e2ac
commit ff275b3764
4 changed files with 63 additions and 22 deletions

@ -70,35 +70,50 @@ oop MethodHandles::popFromStack(TRAPS) {
}
void MethodHandles::throw_AME(Klass* rcvr, Method* interface_method, TRAPS) {
void MethodHandles::setup_frame_anchor(JavaThread* thread) {
assert(!thread->has_last_Java_frame(), "Do not need to call this otherwise");
JavaThread *thread = THREAD->as_Java_thread();
// Set up the frame anchor if it isn't already
intptr_t *sp = thread->zero_stack()->sp();
ZeroFrame *frame = thread->top_zero_frame();
while (frame) {
if (frame->is_interpreter_frame()) {
interpreterState istate = frame->as_interpreter_frame()->interpreter_state();
if (istate->self_link() == istate) break;
}
sp = ((intptr_t *) frame) + 1;
frame = frame->next();
}
assert(frame != NULL, "must be");
thread->set_last_Java_frame(frame, sp);
}
void MethodHandles::teardown_frame_anchor(JavaThread* thread) {
thread->reset_last_Java_frame();
}
void MethodHandles::throw_AME(Klass* rcvr, Method* interface_method, TRAPS) {
JavaThread* thread = THREAD->as_Java_thread();
bool has_last_Java_frame = thread->has_last_Java_frame();
if (!has_last_Java_frame) {
intptr_t *sp = thread->zero_stack()->sp();
ZeroFrame *frame = thread->top_zero_frame();
while (frame) {
if (frame->is_interpreter_frame()) {
interpreterState istate =
frame->as_interpreter_frame()->interpreter_state();
if (istate->self_link() == istate)
break;
}
sp = ((intptr_t *) frame) + 1;
frame = frame->next();
}
assert(frame != NULL, "must be");
thread->set_last_Java_frame(frame, sp);
setup_frame_anchor(thread);
}
InterpreterRuntime::throw_AbstractMethodErrorVerbose(thread, rcvr, interface_method);
// Reset the frame anchor if necessary
if (!has_last_Java_frame) {
thread->reset_last_Java_frame();
teardown_frame_anchor(thread);
}
}
void MethodHandles::throw_NPE(TRAPS) {
JavaThread* thread = THREAD->as_Java_thread();
bool has_last_Java_frame = thread->has_last_Java_frame();
if (!has_last_Java_frame) {
setup_frame_anchor(thread);
}
InterpreterRuntime::throw_NullPointerException(thread);
if (!has_last_Java_frame) {
teardown_frame_anchor(thread);
}
}
int MethodHandles::method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS) {
@ -110,7 +125,14 @@ int MethodHandles::method_handle_entry_invokeBasic(Method* method, intptr_t UNUS
// 'this' is a MethodHandle. We resolve the target method by accessing this.form.vmentry.vmtarget.
int numArgs = method->size_of_parameters();
oop lform1 = java_lang_invoke_MethodHandle::form(STACK_OBJECT(-numArgs)); // this.form
oop recv = STACK_OBJECT(-numArgs);
if (recv == NULL) {
throw_NPE(THREAD);
return 0;
}
oop lform1 = java_lang_invoke_MethodHandle::form(recv); // this.form
oop vmEntry1 = java_lang_invoke_LambdaForm::vmentry(lform1);
Method* vmtarget = (Method*) java_lang_invoke_MemberName::vmtarget(vmEntry1);
@ -150,6 +172,10 @@ int MethodHandles::method_handle_entry_linkToInterface(Method* method, intptr_t
int numArgs = target->size_of_parameters();
oop recv = STACK_OBJECT(-numArgs);
if (recv == NULL) {
throw_NPE(THREAD);
return 0;
}
InstanceKlass* klass_part = InstanceKlass::cast(recv->klass());
itableOffsetEntry* ki = (itableOffsetEntry*) klass_part->start_of_itable();
@ -187,8 +213,14 @@ int MethodHandles::method_handle_entry_linkToVirtual(Method* method, intptr_t UN
// Resolve target method by looking up in the receiver object's vtable.
intptr_t vmindex = java_lang_invoke_MemberName::vmindex(vmentry);
Method* target = (Method*) java_lang_invoke_MemberName::vmtarget(vmentry);
int numArgs = target->size_of_parameters();
oop recv = STACK_OBJECT(-numArgs);
if (recv == NULL) {
throw_NPE(THREAD);
return 0;
}
Klass* clazz = recv->klass();
Klass* klass_part = InstanceKlass::cast(clazz);
ResourceMark rm(THREAD);

@ -32,7 +32,10 @@ enum /* platform_dependent_constants */ {
private:
static oop popFromStack(TRAPS);
static void invoke_target(Method* method, TRAPS);
static void setup_frame_anchor(JavaThread* thread);
static void teardown_frame_anchor(JavaThread* thread);
static void throw_AME(Klass* rcvr, Method* interface_method, TRAPS);
static void throw_NPE(TRAPS);
static int method_handle_entry_invokeBasic(Method* method, intptr_t UNUSED, TRAPS);
static int method_handle_entry_linkToStaticOrSpecial(Method* method, intptr_t UNUSED, TRAPS);
static int method_handle_entry_linkToVirtual(Method* method, intptr_t UNUSED, TRAPS);

@ -632,6 +632,10 @@ JRT_ENTRY(void, InterpreterRuntime::throw_IncompatibleClassChangeErrorVerbose(Ja
THROW_MSG(vmSymbols::java_lang_IncompatibleClassChangeError(), buf);
JRT_END
JRT_ENTRY(void, InterpreterRuntime::throw_NullPointerException(JavaThread* thread))
THROW(vmSymbols::java_lang_NullPointerException());
JRT_END
//------------------------------------------------------------------------------------------------------------------------
// Fields
//

@ -82,6 +82,8 @@ class InterpreterRuntime: AllStatic {
static void throw_delayed_StackOverflowError(JavaThread* thread);
static void throw_ArrayIndexOutOfBoundsException(JavaThread* thread, arrayOopDesc* a, jint index);
static void throw_ClassCastException(JavaThread* thread, oopDesc* obj);
static void throw_NullPointerException(JavaThread* thread);
static void create_exception(JavaThread* thread, char* name, char* message);
static void create_klass_exception(JavaThread* thread, char* name, oopDesc* obj);
static address exception_handler_for_exception(JavaThread* thread, oopDesc* exception);