/* * Copyright (c) 1998, 2022, 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 * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// Eagerly allocate the identity hash code for a klass. This is a fallout // from 6320749 and 8059924: hash code generator is not supposed to be called // during the safepoint, but it allows to sneak the hashcode in during // verification. Without this eager hashcode generation, we may end up // installing the hashcode during some other operation, which may be at // safepoint -- blowing up the checks. It was previously done as the side // effect (sic!) for external_name(), but instead of doing that, we opt to // explicitly push the hashcode in here. This is signify the following block // is IMPORTANT: if (klass->java_mirror() != NULL) {
klass->java_mirror()->identity_hash();
}
if (!is_eligible_for_verification(klass, should_verify_class)) { returntrue;
}
// Timer includes any side effects of class verification (resolution, // etc), but not recursive calls to Verifier::verify().
JavaThread* jt = THREAD;
PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(),
ClassLoader::perf_class_verify_selftime(),
ClassLoader::perf_classes_verified(),
jt->get_thread_stat()->perf_recursion_counts_addr(),
jt->get_thread_stat()->perf_timers_addr(),
PerfClassTraceTime::CLASS_VERIFY);
// If the class should be verified, first see if we can use the split // verifier. If not, or if verification fails and can failover, then // call the inference verifier.
Symbol* exception_name = NULL; const size_t message_buffer_len = klass->name()->utf8_length() + 1024; char* message_buffer = NULL; char* exception_message = NULL;
log_info(class, init)("Start class verification for: %s", klass->external_name()); if (klass->major_version() >= STACKMAP_ATTRIBUTE_MAJOR_VERSION) {
ClassVerifier split_verifier(jt, klass); // We don't use CHECK here, or on inference_verify below, so that we can log any exception.
split_verifier.verify_class(THREAD);
exception_name = split_verifier.result();
// If DumpSharedSpaces is set then don't fall back to the old verifier on // verification failure. If a class fails verification with the split verifier, // it might fail the CDS runtime verifier constraint check. In that case, we // don't want to share the class. We only archive classes that pass the split // verifier. bool can_failover = !DumpSharedSpaces &&
klass->major_version() < NOFAILOVER_MAJOR_VERSION;
if (can_failover && !HAS_PENDING_EXCEPTION && // Split verifier doesn't set PENDING_EXCEPTION for failure
(exception_name == vmSymbols::java_lang_VerifyError() ||
exception_name == vmSymbols::java_lang_ClassFormatError())) {
log_info(verification)("Fail over class verification to old verifier for: %s", klass->external_name());
log_info(class, init)("Fail over class verification to old verifier for: %s", klass->external_name());
message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
exception_message = message_buffer;
exception_name = inference_verify(
klass, message_buffer, message_buffer_len, THREAD);
} if (exception_name != NULL) {
exception_message = split_verifier.exception_message();
}
} else {
message_buffer = NEW_RESOURCE_ARRAY(char, message_buffer_len);
exception_message = message_buffer;
exception_name = inference_verify(
klass, message_buffer, message_buffer_len, THREAD);
}
if (HAS_PENDING_EXCEPTION) { returnfalse; // use the existing exception
} elseif (exception_name == NULL) { returntrue; // verification succeeded
} else { // VerifyError or ClassFormatError to be created and thrown
Klass* kls =
SystemDictionary::resolve_or_fail(exception_name, true, CHECK_false); if (log_is_enabled(Debug, class, resolve)) {
Verifier::trace_class_resolution(kls, klass);
}
while (kls != NULL) { if (kls == klass) { // If the class being verified is the exception we're creating // or one of it's superclasses, we're in trouble and are going // to infinitely recurse when we try to initialize the exception. // So bail out here by throwing the preallocated VM error.
THROW_OOP_(Universe::virtual_machine_error_instance(), false);
}
kls = kls->super();
} if (message_buffer != NULL) {
message_buffer[message_buffer_len - 1] = '\0'; // just to be sure
}
assert(exception_message != NULL, "");
THROW_MSG_(exception_name, exception_message, false);
}
}
return (should_verify_for(klass->class_loader(), should_verify_class) && // return if the class is a bootstrapping class // or defineClass specified not to verify by default (flags override passed arg) // We need to skip the following four for bootstraping
name != vmSymbols::java_lang_Object() &&
name != vmSymbols::java_lang_Class() &&
name != vmSymbols::java_lang_String() &&
name != vmSymbols::java_lang_Throwable() &&
// Can not verify the bytecodes for shared classes because they have // already been rewritten to contain constant pool cache indices, // which the verifier can't understand. // Shared classes shouldn't have stackmaps either. // However, bytecodes for shared old classes can be verified because // they have not been rewritten.
!(klass->is_shared() && klass->is_rewritten()) &&
// As of the fix for 4486457 we disable verification for all of the // dynamically-generated bytecodes associated with the 1.4 // reflection implementation, not just those associated with // jdk/internal/reflect/SerializationConstructorAccessor. // NOTE: this is called too early in the bootstrapping process to be // guarded by Universe::is_gte_jdk14x_version(). // Also for lambda generated code, gte jdk8
(!is_reflect));
}
{
HandleMark hm(thread);
ThreadToNativeFromVM ttn(thread); // ThreadToNativeFromVM takes care of changing thread_state, so safepoint // code knows that we have left the VM
JNIEnv *env = thread->jni_environment();
result = (*verify_func)(env, cls, message, (int)message_len, klass->major_version());
}
JNIHandles::destroy_local(cls);
// These numbers are chosen so that VerifyClassCodes interface doesn't need // to be changed (still return jboolean (unsigned char)), and result is // 1 when verification is passed. if (result == 0) { return vmSymbols::java_lang_VerifyError();
} elseif (result == 1) { return NULL; // verified.
} elseif (result == 2) {
THROW_MSG_(vmSymbols::java_lang_OutOfMemoryError(), message, NULL);
} elseif (result == 3) { return vmSymbols::java_lang_ClassFormatError();
} else {
ShouldNotReachHere(); return NULL;
}
}
void ErrorContext::reason_details(outputStream* ss) const {
streamIndentor si(ss);
ss->indent().print_cr("Reason:");
streamIndentor si2(ss);
ss->indent().print("%s", ""); switch (_fault) { case INVALID_BYTECODE:
ss->print("Error exists in the bytecode"); break; case WRONG_TYPE: if (_expected.is_valid()) {
ss->print("Type ");
_type.details(ss);
ss->print(" is not assignable to ");
_expected.details(ss);
} else {
ss->print("Invalid type: ");
_type.details(ss);
} break; case FLAGS_MISMATCH: if (_expected.is_valid()) {
ss->print("Current frame's flags are not assignable " "to stack map frame's.");
} else {
ss->print("Current frame's flags are invalid in this context.");
} break; case BAD_CP_INDEX:
ss->print("Constant pool index %d is invalid", _type.index()); break; case BAD_LOCAL_INDEX:
ss->print("Local index %d is invalid", _type.index()); break; case LOCALS_SIZE_MISMATCH:
ss->print("Current frame's local size doesn't match stackmap."); break; case STACK_SIZE_MISMATCH:
ss->print("Current frame's stack size doesn't match stackmap."); break; case STACK_OVERFLOW:
ss->print("Exceeded max stack size."); break; case STACK_UNDERFLOW:
ss->print("Attempt to pop empty stack."); break; case MISSING_STACKMAP:
ss->print("Expected stackmap frame at this location."); break; case BAD_STACKMAP:
ss->print("Invalid stackmap specification."); break; case UNKNOWN: default:
ShouldNotReachHere();
ss->print_cr("Unknown");
}
ss->cr();
}
ClassVerifier::~ClassVerifier() { // Decrement the reference count for any symbols created. if (_symbols != NULL) { for (int i = 0; i < _symbols->length(); i++) {
Symbol* s = _symbols->at(i);
s->decrement_refcount();
}
}
}
void ClassVerifier::verify_class(TRAPS) {
log_info(verification)("Verifying class %s with new format", _klass->external_name());
// Either verifying both local and remote classes or just remote classes.
assert(BytecodeVerificationRemote, "Should not be here");
Array<Method*>* methods = _klass->methods(); int num_methods = methods->length();
for (int index = 0; index < num_methods; index++) { // Check for recursive re-verification before each method. if (was_recursively_verified()) return;
Method* m = methods->at(index); if (m->is_native() || m->is_abstract() || m->is_overpass()) { // If m is native or abstract, skip it. It is checked in class file // parser that methods do not override a final method. Overpass methods // are trusted since the VM generates them. continue;
}
verify_method(methodHandle(THREAD, m), CHECK_VERIFY(this));
}
// Translate the signature entries into verification types and save them in // the growable array. Also, save the count of arguments. void ClassVerifier::translate_signature(Symbol* const method_sig,
sig_as_verification_types* sig_verif_types) {
SignatureStream sig_stream(method_sig);
VerificationType sig_type[2]; int sig_i = 0;
GrowableArray<VerificationType>* verif_types = sig_verif_types->sig_verif_types();
// Translate the signature arguments into verification types. while (!sig_stream.at_return_type()) { int n = change_sig_to_verificationType(&sig_stream, sig_type);
assert(n <= 2, "Unexpected signature type");
// Store verification type(s). Longs and Doubles each have two verificationTypes. for (int x = 0; x < n; x++) {
verif_types->push(sig_type[x]);
}
sig_i += n;
sig_stream.next();
}
// Set final arg count, not including the return type. The final arg count will // be compared with sig_verify_types' length to see if there is a return type.
sig_verif_types->set_num_args(sig_i);
// Store verification type(s) for the return type, if there is one. if (sig_stream.type() != T_VOID) { int n = change_sig_to_verificationType(&sig_stream, sig_type);
assert(n <= 2, "Unexpected signature return type"); for (int y = 0; y < n; y++) {
verif_types->push(sig_type[y]);
}
}
}
void ClassVerifier::create_method_sig_entry(sig_as_verification_types* sig_verif_types, int sig_index) { // Translate the signature into verification types.
ConstantPool* cp = _klass->constants();
Symbol* const method_sig = cp->symbol_at(sig_index);
translate_signature(method_sig, sig_verif_types);
// Add the list of this signature's verification types to the table. bool is_unique = method_signatures_table()->put(sig_index, sig_verif_types);
assert(is_unique, "Duplicate entries in method_signature_table");
}
void ClassVerifier::verify_method(const methodHandle& m, TRAPS) {
HandleMark hm(THREAD);
_method = m; // initialize _method
log_info(verification)("Verifying method %s", m->name_and_sig_as_C_string());
// For clang, the only good constant format string is a literal constant format string. #define bad_type_msg "Bad type on operand stack in %s"
// Method signature was checked in ClassFileParser.
assert(SignatureVerifier::is_valid_method_signature(m->signature()), "Invalid method signature");
// Initial stack map frame: offset is 0, stack is initially empty.
StackMapFrame current_frame(max_locals, max_stack, this); // Set initial locals
VerificationType return_type = current_frame.set_locals_from_arg( m, current_type());
int32_t stackmap_index = 0; // index to the stackmap array
u4 code_length = m->code_size();
// Scan the bytecode and map each instruction's start offset to a number. char* code_data = generate_code_data(m, code_length, CHECK_VERIFY(this));
int ex_min = code_length; 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));
// Look through each entry on the local variable table and make sure // its range of code array offsets is valid. (4169817) if (m->has_localvariable_table()) {
verify_local_variable_table(code_length, code_data, CHECK_VERIFY(this));
}
// Scan the byte code linearly from the start to the end bool no_control_flow = false; // Set to true when there is no direct control // flow from current instruction to the next // instruction in sequence
Bytecodes::Code opcode; while (!bcs.is_last_bytecode()) { // Check for recursive re-verification before each bytecode. if (was_recursively_verified()) return;
opcode = bcs.raw_next();
u2 bci = bcs.bci();
// Set current frame's offset to bci
current_frame.set_offset(bci);
current_frame.set_mark();
// Make sure every offset in stackmap table point to the beginning to // an instruction. Match current_frame to stackmap_table entry with // the same offset if exists.
stackmap_index = verify_stackmap_table(
stackmap_index, bci, ¤t_frame, &stackmap_table,
no_control_flow, CHECK_VERIFY(this));
bool this_uninit = false; // Set to true when invokespecial <init> initialized 'this' bool verified_exc_handlers = false;
// Merge with the next instruction
{
u2 index; int target;
VerificationType type, type2;
VerificationType atype;
// Make sure wide instruction is in correct format if (bcs.is_wide()) { if (opcode != Bytecodes::_iinc && opcode != Bytecodes::_iload &&
opcode != Bytecodes::_aload && opcode != Bytecodes::_lload &&
opcode != Bytecodes::_istore && opcode != Bytecodes::_astore &&
opcode != Bytecodes::_lstore && opcode != Bytecodes::_fload &&
opcode != Bytecodes::_dload && opcode != Bytecodes::_fstore &&
opcode != Bytecodes::_dstore) { /* Unreachable? RawBytecodeStream's raw_next() returns 'illegal' * if we encounter a wide instruction that modifies an invalid
* opcode (not one of the ones listed above) */
verify_error(ErrorContext::bad_code(bci), "Bad wide instruction"); return;
}
}
// Look for possible jump target in exception handlers and see if it // matches current_frame. Do this check here for astore*, dstore*, // fstore*, istore*, and lstore* opcodes because they can change the type // state by adding a local. JVM Spec says that the incoming type state // 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; case Bytecodes::_aconst_null :
current_frame.push_stack(
VerificationType::null_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_iconst_m1 : case Bytecodes::_iconst_0 : case Bytecodes::_iconst_1 : case Bytecodes::_iconst_2 : case Bytecodes::_iconst_3 : case Bytecodes::_iconst_4 : case Bytecodes::_iconst_5 :
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_lconst_0 : case Bytecodes::_lconst_1 :
current_frame.push_stack_2(
VerificationType::long_type(),
VerificationType::long2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_fconst_0 : case Bytecodes::_fconst_1 : case Bytecodes::_fconst_2 :
current_frame.push_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_dconst_0 : case Bytecodes::_dconst_1 :
current_frame.push_stack_2(
VerificationType::double_type(),
VerificationType::double2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_sipush : case Bytecodes::_bipush :
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_ldc :
verify_ldc(
opcode, bcs.get_index_u1(), ¤t_frame,
cp, bci, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_ldc_w : case Bytecodes::_ldc2_w :
verify_ldc(
opcode, bcs.get_index_u2(), ¤t_frame,
cp, bci, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_iload :
verify_iload(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_iload_0 : case Bytecodes::_iload_1 : case Bytecodes::_iload_2 : case Bytecodes::_iload_3 :
index = opcode - Bytecodes::_iload_0;
verify_iload(index, ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_lload :
verify_lload(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_lload_0 : case Bytecodes::_lload_1 : case Bytecodes::_lload_2 : case Bytecodes::_lload_3 :
index = opcode - Bytecodes::_lload_0;
verify_lload(index, ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_fload :
verify_fload(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_fload_0 : case Bytecodes::_fload_1 : case Bytecodes::_fload_2 : case Bytecodes::_fload_3 :
index = opcode - Bytecodes::_fload_0;
verify_fload(index, ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_dload :
verify_dload(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_dload_0 : case Bytecodes::_dload_1 : case Bytecodes::_dload_2 : case Bytecodes::_dload_3 :
index = opcode - Bytecodes::_dload_0;
verify_dload(index, ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_aload :
verify_aload(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_aload_0 : case Bytecodes::_aload_1 : case Bytecodes::_aload_2 : case Bytecodes::_aload_3 :
index = opcode - Bytecodes::_aload_0;
verify_aload(index, ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_iaload :
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_int_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[I")),
bad_type_msg, "iaload"); return;
}
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_baload :
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_bool_array() && !atype.is_byte_array()) {
verify_error(
ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
bad_type_msg, "baload"); return;
}
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_caload :
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_char_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[C")),
bad_type_msg, "caload"); return;
}
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_saload :
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_short_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[S")),
bad_type_msg, "saload"); return;
}
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_laload :
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_long_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[J")),
bad_type_msg, "laload"); return;
}
current_frame.push_stack_2(
VerificationType::long_type(),
VerificationType::long2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_faload :
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_float_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[F")),
bad_type_msg, "faload"); return;
}
current_frame.push_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_daload :
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_double_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[D")),
bad_type_msg, "daload"); return;
}
current_frame.push_stack_2(
VerificationType::double_type(),
VerificationType::double2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_aaload : {
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_reference_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(),
TypeOrigin::implicit(VerificationType::reference_check())),
bad_type_msg, "aaload"); return;
} if (atype.is_null()) {
current_frame.push_stack(
VerificationType::null_type(), CHECK_VERIFY(this));
} else {
VerificationType component = atype.get_component(this);
current_frame.push_stack(component, CHECK_VERIFY(this));
}
no_control_flow = false; break;
} case Bytecodes::_istore :
verify_istore(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_istore_0 : case Bytecodes::_istore_1 : case Bytecodes::_istore_2 : case Bytecodes::_istore_3 :
index = opcode - Bytecodes::_istore_0;
verify_istore(index, ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_lstore :
verify_lstore(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_lstore_0 : case Bytecodes::_lstore_1 : case Bytecodes::_lstore_2 : case Bytecodes::_lstore_3 :
index = opcode - Bytecodes::_lstore_0;
verify_lstore(index, ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_fstore :
verify_fstore(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_fstore_0 : case Bytecodes::_fstore_1 : case Bytecodes::_fstore_2 : case Bytecodes::_fstore_3 :
index = opcode - Bytecodes::_fstore_0;
verify_fstore(index, ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_dstore :
verify_dstore(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_dstore_0 : case Bytecodes::_dstore_1 : case Bytecodes::_dstore_2 : case Bytecodes::_dstore_3 :
index = opcode - Bytecodes::_dstore_0;
verify_dstore(index, ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_astore :
verify_astore(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_astore_0 : case Bytecodes::_astore_1 : case Bytecodes::_astore_2 : case Bytecodes::_astore_3 :
index = opcode - Bytecodes::_astore_0;
verify_astore(index, ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_iastore :
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
type2 = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_int_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[I")),
bad_type_msg, "iastore"); return;
}
no_control_flow = false; break; case Bytecodes::_bastore :
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
type2 = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_bool_array() && !atype.is_byte_array()) {
verify_error(
ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
bad_type_msg, "bastore"); return;
}
no_control_flow = false; break; case Bytecodes::_castore :
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_char_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[C")),
bad_type_msg, "castore"); return;
}
no_control_flow = false; break; case Bytecodes::_sastore :
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_short_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[S")),
bad_type_msg, "sastore"); return;
}
no_control_flow = false; break; case Bytecodes::_lastore :
current_frame.pop_stack_2(
VerificationType::long2_type(),
VerificationType::long_type(), CHECK_VERIFY(this));
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_long_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[J")),
bad_type_msg, "lastore"); return;
}
no_control_flow = false; break; case Bytecodes::_fastore :
current_frame.pop_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
current_frame.pop_stack
(VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_float_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[F")),
bad_type_msg, "fastore"); return;
}
no_control_flow = false; break; case Bytecodes::_dastore :
current_frame.pop_stack_2(
VerificationType::double2_type(),
VerificationType::double_type(), CHECK_VERIFY(this));
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); if (!atype.is_double_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(), ref_ctx("[D")),
bad_type_msg, "dastore"); return;
}
no_control_flow = false; break; case Bytecodes::_aastore :
type = current_frame.pop_stack(object_type(), CHECK_VERIFY(this));
type2 = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
atype = current_frame.pop_stack(
VerificationType::reference_check(), CHECK_VERIFY(this)); // more type-checking is done at runtime if (!atype.is_reference_array()) {
verify_error(ErrorContext::bad_type(bci,
current_frame.stack_top_ctx(),
TypeOrigin::implicit(VerificationType::reference_check())),
bad_type_msg, "aastore"); return;
} // 4938384: relaxed constraint in JVMS 3rd edition.
no_control_flow = false; break; case Bytecodes::_pop :
current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_pop2 :
type = current_frame.pop_stack(CHECK_VERIFY(this)); if (type.is_category1()) {
current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
} elseif (type.is_category2_2nd()) {
current_frame.pop_stack(
VerificationType::category2_check(), CHECK_VERIFY(this));
} else { /* Unreachable? Would need a category2_1st on TOS
* which does not appear possible. */
verify_error(
ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
bad_type_msg, "pop2"); return;
}
no_control_flow = false; break; case Bytecodes::_dup :
type = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_dup_x1 :
type = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
type2 = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
current_frame.push_stack(type2, CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_dup_x2 :
{
VerificationType type3;
type = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
type2 = current_frame.pop_stack(CHECK_VERIFY(this)); if (type2.is_category1()) {
type3 = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
} elseif (type2.is_category2_2nd()) {
type3 = current_frame.pop_stack(
VerificationType::category2_check(), CHECK_VERIFY(this));
} else { /* Unreachable? Would need a category2_1st at stack depth 2 with
* a category1 on TOS which does not appear possible. */
verify_error(ErrorContext::bad_type(
bci, current_frame.stack_top_ctx()), bad_type_msg, "dup_x2"); return;
}
current_frame.push_stack(type, CHECK_VERIFY(this));
current_frame.push_stack(type3, CHECK_VERIFY(this));
current_frame.push_stack(type2, CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
no_control_flow = false; break;
} case Bytecodes::_dup2 :
type = current_frame.pop_stack(CHECK_VERIFY(this)); if (type.is_category1()) {
type2 = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
} elseif (type.is_category2_2nd()) {
type2 = current_frame.pop_stack(
VerificationType::category2_check(), CHECK_VERIFY(this));
} else { /* Unreachable? Would need a category2_1st on TOS which does not
* appear possible. */
verify_error(
ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
bad_type_msg, "dup2"); return;
}
current_frame.push_stack(type2, CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
current_frame.push_stack(type2, CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_dup2_x1 :
{
VerificationType type3;
type = current_frame.pop_stack(CHECK_VERIFY(this)); if (type.is_category1()) {
type2 = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
} elseif (type.is_category2_2nd()) {
type2 = current_frame.pop_stack(
VerificationType::category2_check(), CHECK_VERIFY(this));
} else { /* Unreachable? Would need a category2_1st on TOS which does
* not appear possible. */
verify_error(
ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
bad_type_msg, "dup2_x1"); return;
}
type3 = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
current_frame.push_stack(type2, CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
current_frame.push_stack(type3, CHECK_VERIFY(this));
current_frame.push_stack(type2, CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
no_control_flow = false; break;
} case Bytecodes::_dup2_x2 :
{
VerificationType type3, type4;
type = current_frame.pop_stack(CHECK_VERIFY(this)); if (type.is_category1()) {
type2 = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
} elseif (type.is_category2_2nd()) {
type2 = current_frame.pop_stack(
VerificationType::category2_check(), CHECK_VERIFY(this));
} else { /* Unreachable? Would need a category2_1st on TOS which does
* not appear possible. */
verify_error(
ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
bad_type_msg, "dup2_x2"); return;
}
type3 = current_frame.pop_stack(CHECK_VERIFY(this)); if (type3.is_category1()) {
type4 = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
} elseif (type3.is_category2_2nd()) {
type4 = current_frame.pop_stack(
VerificationType::category2_check(), CHECK_VERIFY(this));
} else { /* Unreachable? Would need a category2_1st on TOS after popping * a long/double or two category 1's, which does not
* appear possible. */
verify_error(
ErrorContext::bad_type(bci, current_frame.stack_top_ctx()),
bad_type_msg, "dup2_x2"); return;
}
current_frame.push_stack(type2, CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
current_frame.push_stack(type4, CHECK_VERIFY(this));
current_frame.push_stack(type3, CHECK_VERIFY(this));
current_frame.push_stack(type2, CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
no_control_flow = false; break;
} case Bytecodes::_swap :
type = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
type2 = current_frame.pop_stack(
VerificationType::category1_check(), CHECK_VERIFY(this));
current_frame.push_stack(type, CHECK_VERIFY(this));
current_frame.push_stack(type2, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_iadd : case Bytecodes::_isub : case Bytecodes::_imul : case Bytecodes::_idiv : case Bytecodes::_irem : case Bytecodes::_ishl : case Bytecodes::_ishr : case Bytecodes::_iushr : case Bytecodes::_ior : case Bytecodes::_ixor : case Bytecodes::_iand :
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this)); // fall through case Bytecodes::_ineg :
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_ladd : case Bytecodes::_lsub : case Bytecodes::_lmul : case Bytecodes::_ldiv : case Bytecodes::_lrem : case Bytecodes::_land : case Bytecodes::_lor : case Bytecodes::_lxor :
current_frame.pop_stack_2(
VerificationType::long2_type(),
VerificationType::long_type(), CHECK_VERIFY(this)); // fall through case Bytecodes::_lneg :
current_frame.pop_stack_2(
VerificationType::long2_type(),
VerificationType::long_type(), CHECK_VERIFY(this));
current_frame.push_stack_2(
VerificationType::long_type(),
VerificationType::long2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_lshl : case Bytecodes::_lshr : case Bytecodes::_lushr :
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
current_frame.pop_stack_2(
VerificationType::long2_type(),
VerificationType::long_type(), CHECK_VERIFY(this));
current_frame.push_stack_2(
VerificationType::long_type(),
VerificationType::long2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_fadd : case Bytecodes::_fsub : case Bytecodes::_fmul : case Bytecodes::_fdiv : case Bytecodes::_frem :
current_frame.pop_stack(
VerificationType::float_type(), CHECK_VERIFY(this)); // fall through case Bytecodes::_fneg :
current_frame.pop_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_dadd : case Bytecodes::_dsub : case Bytecodes::_dmul : case Bytecodes::_ddiv : case Bytecodes::_drem :
current_frame.pop_stack_2(
VerificationType::double2_type(),
VerificationType::double_type(), CHECK_VERIFY(this)); // fall through case Bytecodes::_dneg :
current_frame.pop_stack_2(
VerificationType::double2_type(),
VerificationType::double_type(), CHECK_VERIFY(this));
current_frame.push_stack_2(
VerificationType::double_type(),
VerificationType::double2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_iinc :
verify_iinc(bcs.get_index(), ¤t_frame, CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_i2l :
type = current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
current_frame.push_stack_2(
VerificationType::long_type(),
VerificationType::long2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_l2i :
current_frame.pop_stack_2(
VerificationType::long2_type(),
VerificationType::long_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_i2f :
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_i2d :
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
current_frame.push_stack_2(
VerificationType::double_type(),
VerificationType::double2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_l2f :
current_frame.pop_stack_2(
VerificationType::long2_type(),
VerificationType::long_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_l2d :
current_frame.pop_stack_2(
VerificationType::long2_type(),
VerificationType::long_type(), CHECK_VERIFY(this));
current_frame.push_stack_2(
VerificationType::double_type(),
VerificationType::double2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_f2i :
current_frame.pop_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_f2l :
current_frame.pop_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
current_frame.push_stack_2(
VerificationType::long_type(),
VerificationType::long2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_f2d :
current_frame.pop_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
current_frame.push_stack_2(
VerificationType::double_type(),
VerificationType::double2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_d2i :
current_frame.pop_stack_2(
VerificationType::double2_type(),
VerificationType::double_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_d2l :
current_frame.pop_stack_2(
VerificationType::double2_type(),
VerificationType::double_type(), CHECK_VERIFY(this));
current_frame.push_stack_2(
VerificationType::long_type(),
VerificationType::long2_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_d2f :
current_frame.pop_stack_2(
VerificationType::double2_type(),
VerificationType::double_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_i2b : case Bytecodes::_i2c : case Bytecodes::_i2s :
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_lcmp :
current_frame.pop_stack_2(
VerificationType::long2_type(),
VerificationType::long_type(), CHECK_VERIFY(this));
current_frame.pop_stack_2(
VerificationType::long2_type(),
VerificationType::long_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_fcmpl : case Bytecodes::_fcmpg :
current_frame.pop_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
current_frame.pop_stack(
VerificationType::float_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_dcmpl : case Bytecodes::_dcmpg :
current_frame.pop_stack_2(
VerificationType::double2_type(),
VerificationType::double_type(), CHECK_VERIFY(this));
current_frame.pop_stack_2(
VerificationType::double2_type(),
VerificationType::double_type(), CHECK_VERIFY(this));
current_frame.push_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
no_control_flow = false; break; case Bytecodes::_if_icmpeq: case Bytecodes::_if_icmpne: case Bytecodes::_if_icmplt: case Bytecodes::_if_icmpge: case Bytecodes::_if_icmpgt: case Bytecodes::_if_icmple:
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this)); // fall through case Bytecodes::_ifeq: case Bytecodes::_ifne: case Bytecodes::_iflt: case Bytecodes::_ifge: case Bytecodes::_ifgt: case Bytecodes::_ifle:
current_frame.pop_stack(
VerificationType::integer_type(), CHECK_VERIFY(this));
target = bcs.dest();
--> --------------------
--> maximum size reached
--> --------------------
¤ Dauer der Verarbeitung: 0.32 Sekunden
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.