check_code.c revision 2886
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * Copyright (c) 1994, 2009, Oracle and/or its affiliates. All rights reserved.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * This code is free software; you can redistribute it and/or modify it
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * under the terms of the GNU General Public License version 2 only, as
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * published by the Free Software Foundation. Oracle designates this
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * particular file as subject to the "Classpath" exception as provided
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * by Oracle in the LICENSE file that accompanied this code.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * This code is distributed in the hope that it will be useful, but WITHOUT
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
40e5cf3e8f0ddda79b1650df77d0f847a22822bfJazzyNico * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40e5cf3e8f0ddda79b1650df77d0f847a22822bfJazzyNico * version 2 for more details (a copy is included in the LICENSE file that
40e5cf3e8f0ddda79b1650df77d0f847a22822bfJazzyNico * accompanied this code).
40e5cf3e8f0ddda79b1650df77d0f847a22822bfJazzyNico * You should have received a copy of the GNU General Public License version
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * 2 along with this work; if not, write to the Free Software Foundation,
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * or visit www.oracle.com if you need additional information or have any
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * questions.
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * Verify that the code within a method block doesn't exploit any
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * security holes.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico Exported function:
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico VerifyClass(JNIEnv *env, jclass cb, char *message_buffer,
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico jint buffer_length)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico VerifyClassForMajorVersion(JNIEnv *env, jclass cb, char *message_buffer,
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico jint buffer_length, jint major_version)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico This file now only uses the standard JNI and the following VM functions
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico exported in jvm.h:
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_FindClassFromClass
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_IsInterface
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetClassNameUTF
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetClassCPEntriesCount
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetClassCPTypes
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetClassFieldsCount
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetClassMethodsCount
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetFieldIxModifiers
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetMethodIxModifiers
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetMethodIxExceptionTableLength
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetMethodIxLocalsCount
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetMethodIxArgsSize
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetMethodIxMaxStack
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetMethodIxNameUTF
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetMethodIxSignatureUTF
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetMethodIxExceptionsCount
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetMethodIxExceptionIndexes
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetMethodIxByteCodeLength
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetMethodIxByteCode
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetMethodIxExceptionTableEntry
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_IsConstructorIx
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetCPClassNameUTF
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetCPFieldNameUTF
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetCPMethodNameUTF
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetCPFieldSignatureUTF
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetCPMethodSignatureUTF
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetCPFieldClassNameUTF
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetCPMethodClassNameUTF
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico JVM_GetCPFieldModifiers
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_GetCPMethodModifiers
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico JVM_ReleaseUTF
40e5cf3e8f0ddda79b1650df77d0f847a22822bfJazzyNico JVM_IsSameClassPackage
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#include "opcodes.in_out"
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico/* align byte code */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define ALIGN_UP(n,align_grain) (((n) + ((align_grain) - 1)) & ~((align_grain)-1))
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#endif /* ALIGN_UP */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define UCALIGN(n) ((unsigned char *)ALIGN_UP((uintptr_t)(n),sizeof(int)))
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico ITEM_Double_2, /* 2nd word of double in register */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico ITEM_NewObject, /* Like object, but uninitialized. */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico ITEM_InitObject, /* "this" is init method, before call
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico to super() */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico ITEM_ReturnAddress, /* Extra info gives instr # of start pc */
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico /* The following three are only used within array types.
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * Normally, we use ITEM_Integer, instead. */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define MAX(a, b) ((a) > (b) ? (a) : (b))
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define MIN(a, b) ((a) < (b) ? (a) : (b))
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define BITS_PER_INT (CHAR_BIT * sizeof(int)/sizeof(char))
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define SET_BIT(flags, i) (flags[(i)/BITS_PER_INT] |= \
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define IS_BIT_SET(flags, i) (flags[(i)/BITS_PER_INT] & \
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicotypedef unsigned int fullinfo_type;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicotypedef unsigned int *bitvector;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define GET_INDIRECTION(thing) (((thing) & 0xFFFF) >> 5)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define WITH_ZERO_INDIRECTION(thing) ((thing) & ~(0xFFE0))
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define WITH_ZERO_EXTRA_INFO(thing) ((thing) & 0xFFFF)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define NULL_FULLINFO MAKE_FULLINFO(ITEM_Object, 0, 0)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico/* JVM_OPC_invokespecial calls to <init> need to be treated special */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico/* A hash mechanism used by the verifier.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * Maps class names to unique 16 bit integers.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico/* The buckets are managed as a 256 by 256 matrix. We allocate an entire
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * row (256 buckets) at a time to minimize fragmentation. Rows are
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * allocated on demand so that we don't waste too much space.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicotypedef struct hash_bucket_type {
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico unsigned int hash;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico unsigned short ID;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico unsigned short next;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico unsigned loadable:1; /* from context->class loader */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicotypedef struct {
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico unsigned short *table;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico (class_hash->buckets[ID / HASH_ROW_SIZE] + ID % HASH_ROW_SIZE)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * There are currently two types of resources that we need to keep
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * track of (in addition to the CCalloc pool).
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicotypedef struct alloc_stack_type {
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico/* The context type encapsulates the current invocation of the byte
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * code verifier.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico /* buffers etc. */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico alloc_stack_type *allocated_memory; /* all memory blocks that we have not
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico had a chance to free */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico /* Store up to ALLOC_STACK_SIZE number of handles to allocated memory
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico blocks here, to save mallocs. */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico /* these fields are per class */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico unsigned char *constant_types;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico fullinfo_type object_info; /* fullinfo for java/lang/Object */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico fullinfo_type string_info; /* fullinfo for java/lang/String */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico fullinfo_type throwable_info; /* fullinfo for java/lang/Throwable */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico fullinfo_type cloneable_info; /* fullinfo for java/lang/Cloneable */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico fullinfo_type serializable_info; /* fullinfo for java/io/Serializable */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico fullinfo_type currentclass_info; /* fullinfo for context->class */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico fullinfo_type superclass_info; /* fullinfo for superclass */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico /* these fields are per method */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico int *code_data; /* offset to instruction number */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico struct instruction_data_type *instruction_data; /* info about each */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico fullinfo_type *superclasses; /* null terminated superclasses */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico int instruction_count; /* number of instructions */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico fullinfo_type return_type; /* function return type */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico fullinfo_type swap_table[4]; /* used for passing information */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico int bitmask_size; /* words needed to hold bitmap of arguments */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico /* these fields are per field */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico /* Used by the space allocator */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico /* Jump here on any error. */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico /* keep track of how many global refs are allocated. */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico int register_count; /* number of registers used */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico int mask_count; /* number of masks in the following */
40e5cf3e8f0ddda79b1650df77d0f847a22822bfJazzyNicotypedef unsigned short flag_type;
40e5cf3e8f0ddda79b1650df77d0f847a22822bfJazzyNico int opcode; /* may turn into "canonical" opcode */
40e5cf3e8f0ddda79b1650df77d0f847a22822bfJazzyNico unsigned protected:1; /* must accessor be a subclass of "this" */
40e5cf3e8f0ddda79b1650df77d0f847a22822bfJazzyNico int i; /* operand to the opcode */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define FLAG_REACHED 0x01 /* instruction reached */
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico#define FLAG_NEED_CONSTRUCTOR 0x02 /* must call this.<init> or super.<init> */
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico#define FLAG_NO_RETURN 0x04 /* must throw out of method */
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico flag_type or_flags; /* true for at least one path to this inst */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico#define FLAG_CONSTRUCTED 0x01 /* this.<init> or super.<init> called */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico flag_type and_flags; /* true for all paths to this instruction */
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicotypedef struct instruction_data_type instruction_data_type;
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicotypedef struct register_info_type register_info_type;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void read_all_code(context_type *context, jclass cb, int num_methods,
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void verify_method(context_type *context, jclass cb, int index,
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic void free_all_code(context_type* context, int num_methods,
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico unsigned char** code);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic void verify_field(context_type *context, jclass cb, int index);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void verify_opcode_operands (context_type *, unsigned int inumber, int offset);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void set_protected(context_type *, unsigned int inumber, int key, int);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic jboolean is_superclass(context_type *, fullinfo_type);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void initialize_exception_table(context_type *);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic int instruction_length(unsigned char *iptr, unsigned char *end);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic jboolean isLegalTarget(context_type *, int offset);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic void verify_constant_pool_type(context_type *, int, unsigned);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic void check_register_values(context_type *context, unsigned int inumber);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic void check_flags(context_type *context, unsigned int inumber);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void pop_stack(context_type *, unsigned int inumber, stack_info_type *);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void update_registers(context_type *, unsigned int inumber, register_info_type *);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void update_flags(context_type *, unsigned int inumber,
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico flag_type *new_and_flags, flag_type *new_or_flags);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void push_stack(context_type *, unsigned int inumber, stack_info_type *stack);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void merge_into_successors(context_type *, unsigned int inumber,
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic void merge_into_one_successor(context_type *context,
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico unsigned int inumber,
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void merge_stack(context_type *, unsigned int inumber,
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic void merge_registers(context_type *, unsigned int inumber,
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico unsigned int to_inumber,
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void merge_flags(context_type *context, unsigned int from_inumber,
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico unsigned int to_inumber,
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic stack_item_type *copy_stack(context_type *, stack_item_type *);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic mask_type *copy_masks(context_type *, mask_type *masks, int mask_count);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic mask_type *add_to_masks(context_type *, mask_type *, int , int);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic fullinfo_type decrement_indirection(fullinfo_type);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic fullinfo_type merge_fullinfo_types(context_type *context,
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic jclass object_fullinfo_to_classclass(context_type *, fullinfo_type);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico ((type *)CCalloc(context, (count)*(sizeof(type)), JNI_FALSE))
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico ((type *)CCalloc(context, (count)*(sizeof(type)), JNI_TRUE))
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void *CCalloc(context_type *context, int size, jboolean zero);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic fullinfo_type cp_index_to_class_fullinfo(context_type *, int, int);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic char signature_to_fieldtype(context_type *context,
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic void CCerror (context_type *, char *format, ...);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic void CFerror (context_type *, char *format, ...);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico/* Because we can longjmp any time, we need to be very careful about
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * remembering what needs to be freed. */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void check_and_push(context_type *context, const void *ptr, int kind);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic int signature_to_args_size(const char *method_signature);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void print_stack (context_type *, stack_info_type *stack_info);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void print_registers(context_type *, register_info_type *register_info);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void print_flags(context_type *, flag_type, flag_type);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void print_formatted_fieldname(context_type *context, int index);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void print_formatted_methodname(context_type *context, int index);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico hash_table_type *class_hash = &(context->class_hash);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico calloc(MAX_HASH_ENTRIES / HASH_ROW_SIZE, sizeof(hash_bucket_type *));
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic void finalize_class_hash(context_type *context)
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico hash_table_type *class_hash = &(context->class_hash);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico /* 4296677: bucket index starts from 1. */
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico hash_bucket_type *bucket = GET_BUCKET(class_hash, i);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico for (i=0;i<MAX_HASH_ENTRIES / HASH_ROW_SIZE; i++) {
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNiconew_bucket(context_type *context, unsigned short *pID)
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico hash_table_type *class_hash = &(context->class_hash);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico CCerror(context, "Exceeded verifier's limit of 65535 referred classes");
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico class_hash->entries_used++; /* only increment when we are sure there
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico is no overflow. */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic unsigned int
40e5cf3e8f0ddda79b1650df77d0f847a22822bfJazzyNico * Find a class using the defining loader of the current class
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * and return a local reference to it.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic jclass load_class_local(context_type *context,const char *classname)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico jclass cb = JVM_FindClassFromClass(context->env, classname,
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico CCerror(context, "Cannot find class %s", classname);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * Find a class using the defining loader of the current class
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * and return a global reference to it.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic jclass load_class_global(context_type *context, const char *classname)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * Return a unique ID given a local class reference. The loadable
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * flag is true if the defining class loader of context->class
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * is known to be capable of loading the class.
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicostatic unsigned short
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicoclass_to_ID(context_type *context, jclass cb, jboolean loadable)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico hash_table_type *class_hash = &(context->class_hash);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico unsigned int hash;
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico unsigned short *pID;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico pID = &(class_hash->table[hash % HASH_TABLE_SIZE]);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico if (bucket->hash == hash && strcmp(name, bucket->name) == 0) {
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * There is an unresolved entry with our name
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * so we're forced to load it in case it matches us.
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * It's already in the table. Update the loadable
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * state if it's known and then we're done.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico if ((*env)->IsSameObject(env, cb, bucket->class)) {
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * Return a unique ID given a class name from the constant pool.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * All classes are lazily loaded from the defining loader of
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * context->class.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic unsigned short
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicoclass_name_to_ID(context_type *context, const char *name)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico hash_table_type *class_hash = &(context->class_hash);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico unsigned short *pID;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico pID = &(class_hash->table[hash % HASH_TABLE_SIZE]);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico if (bucket->hash == hash && strcmp(name, bucket->name) == 0) {
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * We found at least one matching named entry for a class that
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * was not known to be loadable through the defining class loader
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * of context->class. We must load our named class and update
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * the hash table in case one these entries matches our class.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico unsigned short id = class_to_ID(context, cb, JNI_TRUE);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico bucket->loadable = JNI_TRUE; /* name-only IDs are implicitly loadable */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicostatic const char *
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicoID_to_class_name(context_type *context, unsigned short ID)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico hash_table_type *class_hash = &(context->class_hash);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico hash_bucket_type *bucket = GET_BUCKET(class_hash, ID);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicoID_to_class(context_type *context, unsigned short ID)
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico hash_table_type *class_hash = &(context->class_hash);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico hash_bucket_type *bucket = GET_BUCKET(class_hash, ID);
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico bucket->class = load_class_global(context, bucket->name);
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNicomake_loadable_class_info(context_type *context, jclass cb)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicomake_class_info_from_name(context_type *context, const char *name)
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * 1: on success chosen to be consistent with previous VerifyClass
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * 0: verify error
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * 2: out of memory
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * 3: class format error
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * Called by verify_class. Verify the code of each of the methods
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * in a class. Note that this function apparently can't be JNICALL,
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico * because if it is the dynamic linker doesn't appear to be able to
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico * find it on Win32.
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNicoVerifyClassForMajorVersion(JNIEnv *env, jclass cb, char *buffer, jint len,
f9e7b41ce3997a065b3b520c8c527d190b5e9407JazzyNico unsigned char** code;
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico /* Set invalid method/field index of the context, in case anyone
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico calls CCerror */
09d8c881485db7f6fa367e8f60da0f0a12f83ff8JazzyNico /* Don't call CCerror or anything that can call it above the setjmp! */
if (super != 0) {
while(super != 0) {
super = 0;
if (gptr == 0) {
while(super != 0) {
*gptr = 0;
#ifdef DEBUG
GlobalContext = 0;
#ifdef DEBUG
return result;
static int warned = 0;
if (!warned) {
int* lengths;
unsigned char** code;
for (i = 0; i < num_methods; ++i) {
if (lengths[i] > 0) {
for (i = 0; i < num_methods; ++i) {
int *code_data;
int instruction_count;
int i, offset;
unsigned int inumber;
#ifdef DEBUG
if (verify_verbose) {
const char *methodname =
const char *signature =
if (length <= 0)
if (instruction_count == 0)
for (i = 0; i < nexceptions; i++) {
int var;
switch (opcode) {
case JVM_OPC_jsr:
case JVM_OPC_goto: {
case JVM_OPC_jsr_w:
case JVM_OPC_goto_w: {
case JVM_OPC_tableswitch:
case JVM_OPC_lookupswitch: {
int *lptr;
int *saved_operand;
int keys;
int k, delta;
if (*bptr != 0) {
case JVM_OPC_ldc: {
case JVM_OPC_ldc_w: {
case JVM_OPC_ldc2_w: {
case JVM_OPC_invokevirtual:
case JVM_OPC_invokespecial:
case JVM_OPC_invokestatic:
case JVM_OPC_invokedynamic:
case JVM_OPC_invokeinterface: {
const char *methodname;
if (is_invokedynamic)
if (is_constructor) {
if (is_internal) {
while(super != 0) {
not_found = 0;
if (not_found) {
#ifdef BROKEN_JAVAC
if (has_loader)
unsigned int args1;
unsigned int args2;
const char *signature =
case JVM_OPC_instanceof:
case JVM_OPC_checkcast:
case JVM_OPC_new:
case JVM_OPC_anewarray:
case JVM_OPC_multianewarray: {
switch(opcode) {
case JVM_OPC_anewarray:
case JVM_OPC_new:
case JVM_OPC_multianewarray:
case JVM_OPC_newarray: {
case JVM_T_INT:
case JVM_T_LONG:
case JVM_T_FLOAT:
case JVM_T_DOUBLE:
case JVM_T_CHAR:
case JVM_T_SHORT:
goto check_local_variable;
goto check_local_variable;
goto check_local_variable;
goto check_local_variable2;
goto check_local_variable2;
goto check_local_variable;
goto check_local_variable;
goto check_local_variable;
goto check_local_variable2;
goto check_local_variable2;
case JVM_OPC_wide:
goto check_local_variable2;
goto check_local_variable;
case JVM_OPC_ret:
int access;
} while (calledClass != 0);
static jboolean
if (fptr == 0)
return JNI_FALSE;
return JNI_TRUE;
return JNI_FALSE;
for (; --i >= 0; handler_info++) {
i, &einfo);
const char *classname;
switch (instruction) {
case JVM_OPC_tableswitch: {
int index;
case JVM_OPC_lookupswitch: {
int npairs;
case JVM_OPC_wide:
case JVM_OPC_ret:
case JVM_OPC_iinc:
static jboolean
unsigned type;
const char *signature;
switch (fieldchar) {
unsigned int inumber;
while (work_to_do) {
#ifdef DEBUG
if (verify_verbose) {
#ifdef DEBUG
if (verify_verbose) {
int type;
switch (opcode) {
case JVM_OPC_fload:
case JVM_OPC_aload:
case JVM_OPC_ret:
case JVM_OPC_lload:
case JVM_OPC_dload:
if (!double_word) {
operand);
switch (opcode) {
case JVM_OPC_return:
char *stack_operands, *p;
switch(opcode) {
const char *signature =
operand);
#ifdef DEBUG
if (verify_verbose) {
case JVM_OPC_invokedynamic:
const char *signature =
operand);
#ifdef DEBUG
if (verify_verbose) {
*ip = 0;
case JVM_OPC_multianewarray: {
p > stack_operands;
int type = *--p;
switch (type) {
if ((indirection == 0) ||
switch (opcode) {
case JVM_OPC_putfield:
case JVM_OPC_getfield:
case JVM_OPC_putstatic: {
if (!isAssignableTo
(context,
case JVM_OPC_athrow:
case JVM_OPC_invokeinit:
case JVM_OPC_invokedynamic:
const char *signature =
operand);
int item;
item = 0;
const char *utfName =
is_clone) {
case JVM_OPC_return:
case JVM_OPC_new: {
switch (opcode) {
goto continue_store;
goto continue_store;
for (i = 0; i < register_count; i++)
for (i = 0; i < new_mask_count; i++)
case JVM_OPC_invokeinit:
case JVM_OPC_new: {
for (i = 0; i < register_count; i++) {
for ( ; i < register_count; i++) {
for (k = 0; k < new_mask_count; k++) {
if (!copied_mask) {
for (i = 0; i < new_mask_count; i++) {
for (j = i; j < new_mask_count; j++) {
char *stack_results;
switch(opcode) {
case JVM_CONSTANT_Integer:
case JVM_CONSTANT_Float:
case JVM_CONSTANT_Double:
case JVM_CONSTANT_Long:
case JVM_CONSTANT_String:
case JVM_CONSTANT_Class:
case JVM_CONSTANT_MethodType:
case JVM_CONSTANT_MethodType:
"java/dyn/MethodType");
"java/dyn/MethodHandle");
operand);
#ifdef DEBUG
if (verify_verbose) {
case JVM_OPC_invokeinit:
case JVM_OPC_invokedynamic:
operand);
const char *result_signature;
&full_info);
case JVM_OPC_aconst_null:
case JVM_OPC_new:
case JVM_OPC_checkcast:
case JVM_OPC_newarray:
case JVM_OPC_anewarray:
case JVM_OPC_multianewarray:
case JVM_OPC_aaload:
case JVM_OPC_aload:
for (p = stack_results; *p != 0; p++) {
int type = *p;
switch (type) {
stack_size++; break;
stack_size++; break;
stack_size++; p++;
stack_size++;
int handler_info_length =
int successors_count;
switch (opcode) {
case JVM_OPC_athrow:
successors_count = 0;
case JVM_OPC_ret: {
count++;
case JVM_OPC_tableswitch:
case JVM_OPC_lookupswitch:
#ifdef DEBUG
if (verify_verbose) {
for (i = 0; i < successors_count; i++)
JNI_TRUE);
JNI_TRUE);
for (i = 0; i < successors_count; i++) {
#ifdef DEBUG
#ifdef DEBUG
if (verify_verbose) {
for (i = 0; i < new_register_count; i++) {
for (i = 0; i < new_register_count; i++) {
int *return_mask;
for (i = new_mask_count; --i >= 0; )
new_mask_count = i;
for (i = 0; i < max_registers; i++) {
#ifdef DEBUG
if (change) {
for (i = 0; i < register_count; i++) {
if ((i < new_register_count)
if (copy) {
for (j = i; j < register_count; j++) {
if (i >= new_register_count)
new_registers[j],
while ( register_count > 0
if (mask_count > 0) {
int matches = 0;
for (i = 0; i < mask_count; i++) {
matches++;
!copy_needed && k >= 0;
last_match = j;
for (i = 0; i < matches; i++) {
matches = 0;
for (i = 0; i < mask_count; i++) {
matches++;
last_match = j;
unsigned int to_inumber,
static stack_item_type *
int length;
if (length > 0) {
return new_stack;
return NULL;
static mask_type *
for (i = 0; i < mask_count; i++) {
return result;
static mask_type *
for (i = 0; i < mask_count; i++) {
return result;
int poolPad;
if (new == 0) {
while (this) {
if (new == 0) {
if (new == 0) {
if (zero)
static fullinfo_type
const char *classname;
switch (kind) {
case JVM_CONSTANT_Class:
cp_index);
case JVM_CONSTANT_Methodref:
cp_index);
case JVM_CONSTANT_Fieldref:
cp_index);
return result;
const char *name = 0;
const char *signature = 0;
const char *p = *signature_p;
char result;
int array_depth = 0;
result = 0;
case JVM_SIGNATURE_CHAR:
case JVM_SIGNATURE_SHORT:
case JVM_SIGNATURE_INT:
case JVM_SIGNATURE_FLOAT:
case JVM_SIGNATURE_DOUBLE:
case JVM_SIGNATURE_LONG:
case JVM_SIGNATURE_ARRAY:
array_depth++;
case JVM_SIGNATURE_CLASS: {
int length;
result = 0;
*signature_p = p;
return result;
static fullinfo_type
return NULL_FULLINFO;
if ( (indirection == 0)
static fullinfo_type
return value;
return target;
return value;
return target;
target);
if (is_interface)
return target;
return value;
return target;
return value;
if (dimen_value == 0)
dimen_value--;
if (dimen_target == 0)
dimen_target--;
return result_base;
return value;
return target;
if (cb_target == 0)
if (cb_value == 0)
if (for_assignment) {
while (cb_super_value != 0) {
return target;
while((cb_super_value != 0) &&
(cb_super_target != 0)) {
return target;
return value;
while (cb_super_value != 0) {
while (cb_super_target != 0) {
return result_info;
static jclass
switch (kind) {
case VM_STRING_UTF:
case VM_MALLOC_BLK:
alloc_stack_type *p;
if (ptr == 0)
free(p);
int args_size = 0;
case JVM_SIGNATURE_BOOLEAN:
case JVM_SIGNATURE_BYTE:
case JVM_SIGNATURE_CHAR:
case JVM_SIGNATURE_SHORT:
case JVM_SIGNATURE_INT:
case JVM_SIGNATURE_FLOAT:
case JVM_SIGNATURE_CLASS:
while (*p != JVM_SIGNATURE_ENDCLASS) p++;
case JVM_SIGNATURE_ARRAY:
while ((*p == JVM_SIGNATURE_ARRAY)) p++;
if (*p == JVM_SIGNATURE_CLASS) {
while (*p != JVM_SIGNATURE_ENDCLASS)
case JVM_SIGNATURE_DOUBLE:
case JVM_SIGNATURE_LONG:
return args_size;
#ifdef DEBUG
for (i = 0; i < register_count; i++)
for (i = 0; i < mask_count; i++) {
for (i = indirection; i-- > 0; )
case ITEM_Integer:
case ITEM_Float:
case ITEM_Double:
case ITEM_Double_2:
case ITEM_Long:
case ITEM_Long_2:
case ITEM_ReturnAddress:
case ITEM_Object:
if (!verbose) {
if (extra == 0) {
case ITEM_Char:
case ITEM_Short:
case ITEM_Byte:
case ITEM_NewObject:
if (!verbose) {
case ITEM_InitObject:
for (i = indirection; i-- > 0; )