Path: blob/aarch64-shenandoah-jdk8u272-b10/hotspot/src/share/vm/classfile/verifier.hpp
32285 views
/*1* Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*22*/2324#ifndef SHARE_VM_CLASSFILE_VERIFIER_HPP25#define SHARE_VM_CLASSFILE_VERIFIER_HPP2627#include "classfile/verificationType.hpp"28#include "memory/gcLocker.hpp"29#include "oops/klass.hpp"30#include "oops/method.hpp"31#include "runtime/handles.hpp"32#include "utilities/growableArray.hpp"33#include "utilities/exceptions.hpp"3435// The verifier class36class Verifier : AllStatic {37public:38enum {39STRICTER_ACCESS_CTRL_CHECK_VERSION = 49,40STACKMAP_ATTRIBUTE_MAJOR_VERSION = 50,41INVOKEDYNAMIC_MAJOR_VERSION = 51,42NO_RELAX_ACCESS_CTRL_CHECK_VERSION = 5243};44typedef enum { ThrowException, NoException } Mode;4546/**47* Verify the bytecodes for a class. If 'throw_exception' is true48* then the appropriate VerifyError or ClassFormatError will be thrown.49* Otherwise, no exception is thrown and the return indicates the50* error.51*/52static bool verify(instanceKlassHandle klass, Mode mode, bool should_verify_class, TRAPS);5354// Return false if the class is loaded by the bootstrap loader,55// or if defineClass was called requesting skipping verification56// -Xverify:all/none override this value57static bool should_verify_for(oop class_loader, bool should_verify_class);5859// Relax certain access checks to enable some broken 1.1 apps to run on 1.2.60static bool relax_access_for(oop class_loader);6162private:63static bool is_eligible_for_verification(instanceKlassHandle klass, bool should_verify_class);64static Symbol* inference_verify(65instanceKlassHandle klass, char* msg, size_t msg_len, TRAPS);66};6768class RawBytecodeStream;69class StackMapFrame;70class StackMapTable;7172// Summary of verifier's memory usage:73// StackMapTable is stack allocated.74// StackMapFrame are resource allocated. There is only one ResourceMark75// for each class verification, which is created at the top level.76// There is one mutable StackMapFrame (current_frame) which is updated77// by abstract bytecode interpretation. frame_in_exception_handler() returns78// a frame that has a mutable one-item stack (ready for pushing the79// catch type exception object). All the other StackMapFrame's80// are immutable (including their locals and stack arrays) after81// their constructions.82// locals/stack arrays in StackMapFrame are resource allocated.83// locals/stack arrays can be shared between StackMapFrame's, except84// the mutable StackMapFrame (current_frame).8586// These macros are used similarly to CHECK macros but also check87// the status of the verifier and return if that has an error.88#define CHECK_VERIFY(verifier) \89CHECK); if ((verifier)->has_error()) return; ((void)090#define CHECK_VERIFY_(verifier, result) \91CHECK_(result)); if ((verifier)->has_error()) return (result); ((void)09293class TypeOrigin VALUE_OBJ_CLASS_SPEC {94private:95typedef enum {96CF_LOCALS, // Comes from the current frame locals97CF_STACK, // Comes from the current frame expression stack98SM_LOCALS, // Comes from stackmap locals99SM_STACK, // Comes from stackmap expression stack100CONST_POOL, // Comes from the constant pool101SIG, // Comes from method signature102IMPLICIT, // Comes implicitly from code or context103BAD_INDEX, // No type, but the index is bad104FRAME_ONLY, // No type, context just contains the frame105NONE106} Origin;107108Origin _origin;109u2 _index; // local, stack, or constant pool index110StackMapFrame* _frame; // source frame if CF or SM111VerificationType _type; // The actual type112113TypeOrigin(114Origin origin, u2 index, StackMapFrame* frame, VerificationType type)115: _origin(origin), _index(index), _frame(frame), _type(type) {}116117public:118TypeOrigin() : _origin(NONE), _index(0), _frame(NULL) {}119120static TypeOrigin null();121static TypeOrigin local(u2 index, StackMapFrame* frame);122static TypeOrigin stack(u2 index, StackMapFrame* frame);123static TypeOrigin sm_local(u2 index, StackMapFrame* frame);124static TypeOrigin sm_stack(u2 index, StackMapFrame* frame);125static TypeOrigin cp(u2 index, VerificationType vt);126static TypeOrigin signature(VerificationType vt);127static TypeOrigin bad_index(u2 index);128static TypeOrigin implicit(VerificationType t);129static TypeOrigin frame(StackMapFrame* frame);130131void reset_frame();132void details(outputStream* ss) const;133void print_frame(outputStream* ss) const;134const StackMapFrame* frame() const { return _frame; }135bool is_valid() const { return _origin != NONE; }136u2 index() const { return _index; }137138#ifdef ASSERT139void print_on(outputStream* str) const;140#endif141};142143class ErrorContext VALUE_OBJ_CLASS_SPEC {144private:145typedef enum {146INVALID_BYTECODE, // There was a problem with the bytecode147WRONG_TYPE, // Type value was not as expected148FLAGS_MISMATCH, // Frame flags are not assignable149BAD_CP_INDEX, // Invalid constant pool index150BAD_LOCAL_INDEX, // Invalid local index151LOCALS_SIZE_MISMATCH, // Frames have differing local counts152STACK_SIZE_MISMATCH, // Frames have different stack sizes153STACK_OVERFLOW, // Attempt to push onto a full expression stack154STACK_UNDERFLOW, // Attempt to pop and empty expression stack155MISSING_STACKMAP, // No stackmap for this location and there should be156BAD_STACKMAP, // Format error in stackmap157NO_FAULT, // No error158UNKNOWN159} FaultType;160161int _bci;162FaultType _fault;163TypeOrigin _type;164TypeOrigin _expected;165166ErrorContext(int bci, FaultType fault) :167_bci(bci), _fault(fault) {}168ErrorContext(int bci, FaultType fault, TypeOrigin type) :169_bci(bci), _fault(fault), _type(type) {}170ErrorContext(int bci, FaultType fault, TypeOrigin type, TypeOrigin exp) :171_bci(bci), _fault(fault), _type(type), _expected(exp) {}172173public:174ErrorContext() : _bci(-1), _fault(NO_FAULT) {}175176static ErrorContext bad_code(u2 bci) {177return ErrorContext(bci, INVALID_BYTECODE);178}179static ErrorContext bad_type(u2 bci, TypeOrigin type) {180return ErrorContext(bci, WRONG_TYPE, type);181}182static ErrorContext bad_type(u2 bci, TypeOrigin type, TypeOrigin exp) {183return ErrorContext(bci, WRONG_TYPE, type, exp);184}185static ErrorContext bad_flags(u2 bci, StackMapFrame* frame) {186return ErrorContext(bci, FLAGS_MISMATCH, TypeOrigin::frame(frame));187}188static ErrorContext bad_flags(u2 bci, StackMapFrame* cur, StackMapFrame* sm) {189return ErrorContext(bci, FLAGS_MISMATCH,190TypeOrigin::frame(cur), TypeOrigin::frame(sm));191}192static ErrorContext bad_cp_index(u2 bci, u2 index) {193return ErrorContext(bci, BAD_CP_INDEX, TypeOrigin::bad_index(index));194}195static ErrorContext bad_local_index(u2 bci, u2 index) {196return ErrorContext(bci, BAD_LOCAL_INDEX, TypeOrigin::bad_index(index));197}198static ErrorContext locals_size_mismatch(199u2 bci, StackMapFrame* frame0, StackMapFrame* frame1) {200return ErrorContext(bci, LOCALS_SIZE_MISMATCH,201TypeOrigin::frame(frame0), TypeOrigin::frame(frame1));202}203static ErrorContext stack_size_mismatch(204u2 bci, StackMapFrame* frame0, StackMapFrame* frame1) {205return ErrorContext(bci, STACK_SIZE_MISMATCH,206TypeOrigin::frame(frame0), TypeOrigin::frame(frame1));207}208static ErrorContext stack_overflow(u2 bci, StackMapFrame* frame) {209return ErrorContext(bci, STACK_OVERFLOW, TypeOrigin::frame(frame));210}211static ErrorContext stack_underflow(u2 bci, StackMapFrame* frame) {212return ErrorContext(bci, STACK_UNDERFLOW, TypeOrigin::frame(frame));213}214static ErrorContext missing_stackmap(u2 bci) {215return ErrorContext(bci, MISSING_STACKMAP);216}217static ErrorContext bad_stackmap(int index, StackMapFrame* frame) {218return ErrorContext(0, BAD_STACKMAP, TypeOrigin::frame(frame));219}220221bool is_valid() const { return _fault != NO_FAULT; }222int bci() const { return _bci; }223224void reset_frames() {225_type.reset_frame();226_expected.reset_frame();227}228229void details(outputStream* ss, const Method* method) const;230231#ifdef ASSERT232void print_on(outputStream* str) const {233str->print("error_context(%d, %d,", _bci, _fault);234_type.print_on(str);235str->print(",");236_expected.print_on(str);237str->print(")");238}239#endif240241private:242void location_details(outputStream* ss, const Method* method) const;243void reason_details(outputStream* ss) const;244void frame_details(outputStream* ss) const;245void bytecode_details(outputStream* ss, const Method* method) const;246void handler_details(outputStream* ss, const Method* method) const;247void stackmap_details(outputStream* ss, const Method* method) const;248};249250// A new instance of this class is created for each class being verified251class ClassVerifier : public StackObj {252private:253Thread* _thread;254GrowableArray<Symbol*>* _symbols; // keep a list of symbols created255256Symbol* _exception_type;257char* _message;258259ErrorContext _error_context; // contains information about an error260261void verify_method(methodHandle method, TRAPS);262char* generate_code_data(methodHandle m, u4 code_length, TRAPS);263void verify_exception_handler_table(u4 code_length, char* code_data,264int& min, int& max, TRAPS);265void verify_local_variable_table(u4 code_length, char* code_data, TRAPS);266267VerificationType cp_ref_index_to_type(268int index, constantPoolHandle cp, TRAPS) {269return cp_index_to_type(cp->klass_ref_index_at(index), cp, THREAD);270}271272bool is_protected_access(273instanceKlassHandle this_class, Klass* target_class,274Symbol* field_name, Symbol* field_sig, bool is_method);275276void verify_cp_index(u2 bci, constantPoolHandle cp, int index, TRAPS);277void verify_cp_type(u2 bci, int index, constantPoolHandle cp,278unsigned int types, TRAPS);279void verify_cp_class_type(u2 bci, int index, constantPoolHandle cp, TRAPS);280281u2 verify_stackmap_table(282u2 stackmap_index, u2 bci, StackMapFrame* current_frame,283StackMapTable* stackmap_table, bool no_control_flow, TRAPS);284285void verify_exception_handler_targets(286u2 bci, bool this_uninit, StackMapFrame* current_frame,287StackMapTable* stackmap_table, TRAPS);288289void verify_ldc(290int opcode, u2 index, StackMapFrame *current_frame,291constantPoolHandle cp, u2 bci, TRAPS);292293void verify_switch(294RawBytecodeStream* bcs, u4 code_length, char* code_data,295StackMapFrame* current_frame, StackMapTable* stackmap_table, TRAPS);296297void verify_field_instructions(298RawBytecodeStream* bcs, StackMapFrame* current_frame,299constantPoolHandle cp, TRAPS);300301void verify_invoke_init(302RawBytecodeStream* bcs, u2 ref_index, VerificationType ref_class_type,303StackMapFrame* current_frame, u4 code_length, bool in_try_block,304bool* this_uninit, constantPoolHandle cp, StackMapTable* stackmap_table,305TRAPS);306307// Used by ends_in_athrow() to push all handlers that contain bci onto the308// handler_stack, if the handler has not already been pushed on the stack.309void push_handlers(ExceptionTable* exhandlers,310GrowableArray<u4>* handler_list,311GrowableArray<u4>* handler_stack,312u4 bci);313314// Returns true if all paths starting with start_bc_offset end in athrow315// bytecode or loop.316bool ends_in_athrow(u4 start_bc_offset);317318void verify_invoke_instructions(319RawBytecodeStream* bcs, u4 code_length, StackMapFrame* current_frame,320bool in_try_block, bool* this_uninit, VerificationType return_type,321constantPoolHandle cp, StackMapTable* stackmap_table, TRAPS);322323VerificationType get_newarray_type(u2 index, u2 bci, TRAPS);324void verify_anewarray(u2 bci, u2 index, constantPoolHandle cp,325StackMapFrame* current_frame, TRAPS);326void verify_return_value(327VerificationType return_type, VerificationType type, u2 offset,328StackMapFrame* current_frame, TRAPS);329330void verify_iload (u2 index, StackMapFrame* current_frame, TRAPS);331void verify_lload (u2 index, StackMapFrame* current_frame, TRAPS);332void verify_fload (u2 index, StackMapFrame* current_frame, TRAPS);333void verify_dload (u2 index, StackMapFrame* current_frame, TRAPS);334void verify_aload (u2 index, StackMapFrame* current_frame, TRAPS);335void verify_istore(u2 index, StackMapFrame* current_frame, TRAPS);336void verify_lstore(u2 index, StackMapFrame* current_frame, TRAPS);337void verify_fstore(u2 index, StackMapFrame* current_frame, TRAPS);338void verify_dstore(u2 index, StackMapFrame* current_frame, TRAPS);339void verify_astore(u2 index, StackMapFrame* current_frame, TRAPS);340void verify_iinc (u2 index, StackMapFrame* current_frame, TRAPS);341342bool name_in_supers(Symbol* ref_name, instanceKlassHandle current);343344VerificationType object_type() const;345346instanceKlassHandle _klass; // the class being verified347methodHandle _method; // current method being verified348VerificationType _this_type; // the verification type of the current class349350// Some recursive calls from the verifier to the name resolver351// can cause the current class to be re-verified and rewritten.352// If this happens, the original verification should not continue,353// because constant pool indexes will have changed.354// The rewriter is preceded by the verifier. If the verifier throws355// an error, rewriting is prevented. Also, rewriting always precedes356// bytecode execution or compilation. Thus, is_rewritten implies357// that a class has been verified and prepared for execution.358bool was_recursively_verified() { return _klass->is_rewritten(); }359360bool is_same_or_direct_interface(instanceKlassHandle klass,361VerificationType klass_type, VerificationType ref_class_type);362363public:364enum {365BYTECODE_OFFSET = 1,366NEW_OFFSET = 2367};368369// constructor370ClassVerifier(instanceKlassHandle klass, TRAPS);371372// destructor373~ClassVerifier();374375Thread* thread() { return _thread; }376methodHandle method() { return _method; }377instanceKlassHandle current_class() const { return _klass; }378VerificationType current_type() const { return _this_type; }379380// Verifies the class. If a verify or class file format error occurs,381// the '_exception_name' symbols will set to the exception name and382// the message_buffer will be filled in with the exception message.383void verify_class(TRAPS);384385// Return status modes386Symbol* result() const { return _exception_type; }387bool has_error() const { return result() != NULL; }388char* exception_message() {389stringStream ss;390ss.print("%s", _message);391_error_context.details(&ss, _method());392return ss.as_string();393}394395// Called when verify or class format errors are encountered.396// May throw an exception based upon the mode.397void verify_error(ErrorContext ctx, const char* fmt, ...) ATTRIBUTE_PRINTF(3, 4);398void class_format_error(const char* fmt, ...) ATTRIBUTE_PRINTF(2, 3);399400Klass* load_class(Symbol* name, TRAPS);401402int change_sig_to_verificationType(403SignatureStream* sig_type, VerificationType* inference_type, TRAPS);404405VerificationType cp_index_to_type(int index, constantPoolHandle cp, TRAPS) {406return VerificationType::reference_type(cp->klass_name_at(index));407}408409// Keep a list of temporary symbols created during verification because410// their reference counts need to be decrememented when the verifier object411// goes out of scope. Since these symbols escape the scope in which they're412// created, we can't use a TempNewSymbol.413Symbol* create_temporary_symbol(414const Symbol* s, int begin, int end, TRAPS);415Symbol* create_temporary_symbol(const char *s, int length, TRAPS);416417TypeOrigin ref_ctx(const char* str, TRAPS);418419};420421inline int ClassVerifier::change_sig_to_verificationType(422SignatureStream* sig_type, VerificationType* inference_type, TRAPS) {423BasicType bt = sig_type->type();424switch (bt) {425case T_OBJECT:426case T_ARRAY:427{428Symbol* name = sig_type->as_symbol(CHECK_0);429// Create another symbol to save as signature stream unreferences430// this symbol.431Symbol* name_copy =432create_temporary_symbol(name, 0, name->utf8_length(), CHECK_0);433assert(name_copy == name, "symbols don't match");434*inference_type =435VerificationType::reference_type(name_copy);436return 1;437}438case T_LONG:439*inference_type = VerificationType::long_type();440*++inference_type = VerificationType::long2_type();441return 2;442case T_DOUBLE:443*inference_type = VerificationType::double_type();444*++inference_type = VerificationType::double2_type();445return 2;446case T_INT:447case T_BOOLEAN:448case T_BYTE:449case T_CHAR:450case T_SHORT:451*inference_type = VerificationType::integer_type();452return 1;453case T_FLOAT:454*inference_type = VerificationType::float_type();455return 1;456default:457ShouldNotReachHere();458return 1;459}460}461462#endif // SHARE_VM_CLASSFILE_VERIFIER_HPP463464465