--- a/hotspot/src/share/vm/classfile/verifier.cpp Wed Jan 27 11:41:44 2016 +0100
+++ b/hotspot/src/share/vm/classfile/verifier.cpp Wed Jan 27 07:14:56 2016 -0500
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -651,6 +651,7 @@
int ex_max = -1;
// Look through each item on the exception table. Each of the fields must refer
// to a legal instruction.
+ if (was_recursively_verified()) return;
verify_exception_handler_table(
code_length, code_data, ex_min, ex_max, CHECK_VERIFY(this));
@@ -737,11 +738,14 @@
// should be used for this check. So, do the check here before a possible
// local is added to the type state.
if (Bytecodes::is_store_into_local(opcode) && bci >= ex_min && bci < ex_max) {
+ if (was_recursively_verified()) return;
verify_exception_handler_targets(
bci, this_uninit, ¤t_frame, &stackmap_table, CHECK_VERIFY(this));
verified_exc_handlers = true;
}
+ if (was_recursively_verified()) return;
+
switch (opcode) {
case Bytecodes::_nop :
no_control_flow = false; break;
@@ -1730,6 +1734,7 @@
assert(!(verified_exc_handlers && this_uninit),
"Exception handler targets got verified before this_uninit got set");
if (!verified_exc_handlers && bci >= ex_min && bci < ex_max) {
+ if (was_recursively_verified()) return;
verify_exception_handler_targets(
bci, this_uninit, ¤t_frame, &stackmap_table, CHECK_VERIFY(this));
}
@@ -1767,6 +1772,9 @@
return code_data;
}
+// Since this method references the constant pool, call was_recursively_verified()
+// before calling this method to make sure a prior class load did not cause the
+// current class to get verified.
void ClassVerifier::verify_exception_handler_table(u4 code_length, char* code_data, int& min, int& max, TRAPS) {
ExceptionTable exhandlers(_method());
int exlength = exhandlers.length();
@@ -1874,7 +1882,11 @@
return stackmap_index;
}
-void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit, StackMapFrame* current_frame,
+// Since this method references the constant pool, call was_recursively_verified()
+// before calling this method to make sure a prior class load did not cause the
+// current class to get verified.
+void ClassVerifier::verify_exception_handler_targets(u2 bci, bool this_uninit,
+ StackMapFrame* current_frame,
StackMapTable* stackmap_table, TRAPS) {
constantPoolHandle cp (THREAD, _method->constants());
ExceptionTable exhandlers(_method());
@@ -1889,6 +1901,7 @@
if (this_uninit) { flags |= FLAG_THIS_UNINIT; }
StackMapFrame* new_frame = current_frame->frame_in_exception_handler(flags);
if (catch_type_index != 0) {
+ if (was_recursively_verified()) return;
// We know that this index refers to a subclass of Throwable
VerificationType catch_type = cp_index_to_type(
catch_type_index, cp, CHECK_VERIFY(this));
@@ -2269,6 +2282,7 @@
check_protected: {
if (_this_type == stack_object_type)
break; // stack_object_type must be assignable to _current_class_type
+ if (was_recursively_verified()) return;
Symbol* ref_class_name =
cp->klass_name_at(cp->klass_ref_index_at(index));
if (!name_in_supers(ref_class_name, current_class()))
@@ -2531,6 +2545,7 @@
// Check the exception handler target stackmaps with the locals from the
// incoming stackmap (before initialize_object() changes them to outgoing
// state).
+ if (was_recursively_verified()) return;
verify_exception_handler_targets(bci, true, current_frame,
stackmap_table, CHECK_VERIFY(this));
} // in_try_block
@@ -2548,6 +2563,7 @@
return;
}
u2 new_class_index = Bytes::get_Java_u2(new_bcp + 1);
+ if (was_recursively_verified()) return;
verify_cp_class_type(bci, new_class_index, cp, CHECK_VERIFY(this));
// The method must be an <init> method of the indicated class
@@ -2567,6 +2583,7 @@
VerificationType objectref_type = new_class_type;
if (name_in_supers(ref_class_type.name(), current_class())) {
Klass* ref_klass = load_class(ref_class_type.name(), CHECK);
+ if (was_recursively_verified()) return;
Method* m = InstanceKlass::cast(ref_klass)->uncached_lookup_method(
vmSymbols::object_initializer_name(),
cp->signature_ref_at(bcs->get_index_u2()),
@@ -2591,6 +2608,7 @@
// incoming stackmap (before initialize_object() changes them to outgoing
// state).
if (in_try_block) {
+ if (was_recursively_verified()) return;
verify_exception_handler_targets(bci, *this_uninit, current_frame,
stackmap_table, CHECK_VERIFY(this));
}
@@ -2791,6 +2809,7 @@
verify_invoke_init(bcs, index, ref_class_type, current_frame,
code_length, in_try_block, this_uninit, cp, stackmap_table,
CHECK_VERIFY(this));
+ if (was_recursively_verified()) return;
} else { // other methods
// Ensures that target class is assignable to method class.
if (opcode == Bytecodes::_invokespecial) {
@@ -2816,6 +2835,7 @@
VerificationType stack_object_type =
current_frame->pop_stack(ref_class_type, CHECK_VERIFY(this));
if (current_type() != stack_object_type) {
+ if (was_recursively_verified()) return;
assert(cp->cache() == NULL, "not rewritten yet");
Symbol* ref_class_name =
cp->klass_name_at(cp->klass_ref_index_at(index));
@@ -2894,6 +2914,7 @@
current_frame->pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
+ if (was_recursively_verified()) return;
VerificationType component_type =
cp_index_to_type(index, cp, CHECK_VERIFY(this));
int length;