| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #ifndef __TPOOL_H_ |
| #define __TPOOL_H_ |
| |
| #include "open/vm_class_manipulation.h" |
| |
| #include "verifier.h" |
| #include "stackmap.h" |
| #include "memory.h" |
| #include "ver_utils.h" |
| |
| /** |
| * Verification type constraint structure. |
| */ |
| struct vf_TypeConstraint { |
| const char *source; // constraint source class name |
| const char *target; // constraint target class name |
| vf_TypeConstraint *next; // next constraint |
| }; |
| typedef vf_TypeConstraint* vf_TypeConstraint_p; |
| |
| //verifier's data stored in classloader |
| typedef struct { |
| Memory *pool; // constraint memory pool |
| vf_Hash *hash; // constraint hash table |
| vf_Hash *string; // string pool hash table |
| } vf_ClassLoaderData_t; |
| |
| |
| struct vf_ValidType { |
| Class_Handle cls; //class handler |
| const char* name; //name of the class |
| }; |
| |
| #define CLASS_NOT_LOADED ((Class_Handle)-1) |
| |
| class SharedClasswideData; |
| |
| /** |
| * Utility class for dealing with Java types, converting object references to SmConstant, |
| * parsing constantpool, etc. |
| * TODO: remove constant pool parse and verification from the bytecode verifier. |
| */ |
| class vf_TypePool { |
| |
| public: |
| vf_TypePool(SharedClasswideData *_classwide, Class_Handle _klass, unsigned table_incr); |
| |
| ~vf_TypePool() { |
| if( validTypes ) tc_free(validTypes); |
| } |
| |
| SmConstant cpool_get_ldcarg(unsigned short cp_idx); |
| SmConstant cpool_get_ldc2arg(unsigned short cp_idx); |
| int cpool_is_reftype(unsigned short cp_idx); |
| int cpool_get_class(unsigned short cp_idx, SmConstant *ref, int expected_dim = 0); |
| |
| int cpool_get_array(unsigned short cp_idx, SmConstant *ref); |
| int cpool_get_field(unsigned short cp_idx, SmConstant *ref, SmConstant *value); |
| int cpool_method_start(unsigned short cp_idx, const char **state, SmConstant *objectref, |
| unsigned short *name_idx, int opcode); |
| int cpool_method_get_rettype(const char **state, SmConstant *rettype, int *args_sz); |
| int cpool_method_next_arg(const char **state, SmConstant *argument); |
| int cpool_method_is_constructor_call(unsigned short name_idx); |
| |
| |
| SmConstant get_type(const char *type_name, int name_len); |
| SmConstant get_ref_type(const char *type_name, int name_len); |
| SmConstant get_primitive_type(const char type_char); |
| SmConstant get_ref_from_array(SmConstant element); |
| |
| |
| SmConstant get_type(const char *type_name) { |
| return get_type(type_name, (int)strlen(type_name) ); |
| } |
| |
| SmConstant get_ref_type(const char *type_name) { |
| return get_ref_type(type_name, (int)strlen(type_name) ); |
| } |
| |
| int mustbe_assignable(SmConstant from, SmConstant to); |
| int ref_mustbe_assignable(SmConstant from, SmConstant to); |
| |
| |
| vf_ValidType *getVaildType(unsigned index) { |
| assert(index && validTypes && index < validTypesTableSz); |
| return validTypes + index; |
| } |
| |
| Class_Handle sm_get_handler(SmConstant type) { |
| unsigned index = type.getReferenceIdx(); |
| return getVaildType(index)->cls; |
| } |
| |
| const char* sm_get_refname(SmConstant type) { |
| unsigned index = type.getReferenceIdx(); |
| return getVaildType(index)->name; |
| } |
| |
| //return SmConstant (known verification type) corresponding to 'type_name' and cache result in the 'cache' |
| SmConstant sm_get_const_existing(const char* type_name, SmConstant* cache) { |
| if( (*cache) == SM_NONE ) { |
| //TODO: check asm code for strlen |
| (*cache) = get_ref_type(type_name, (int)strlen(type_name)); |
| } |
| return (*cache); |
| } |
| |
| //return SmConstant (known verification type) corresponding to the super class of the class being verified |
| //returned value is cached |
| SmConstant sm_get_const_super() { |
| const char* _super = class_get_name( class_get_super_class( k_class )); |
| return get_ref_type(_super, (int)strlen(_super) ); |
| } |
| |
| //return SmConstant (known verification type) corresponding to the class being verified |
| //returned value is cached |
| SmConstant sm_get_const_this() { |
| return sm_get_const_existing(class_get_name(k_class), &const_this); |
| } |
| |
| //return SmConstant (known verification type) corresponding to java/lang/Object |
| //returned value is cached |
| SmConstant sm_get_const_object() { |
| return sm_get_const_existing("java/lang/Object", &const_object); |
| } |
| |
| //return SmConstant (known verification type) corresponding to java/lang/Class |
| //returned value is cached |
| SmConstant sm_get_const_class() { |
| return sm_get_const_existing("java/lang/Class", &const_class); |
| } |
| |
| //return SmConstant (known verification type) corresponding to java/lang/String |
| //returned value is cached |
| SmConstant sm_get_const_string() { |
| return sm_get_const_existing("java/lang/String", &const_string); |
| } |
| |
| //return SmConstant (known verification type) corresponding to java/lang/Throwable |
| //returned value is cached |
| SmConstant sm_get_const_throwable() { |
| return sm_get_const_existing("java/lang/Throwable", &const_throwable); |
| } |
| |
| //return SmConstant (known verification type) corresponding to U_8[] |
| //returned value is cached |
| SmConstant sm_get_const_arrayref_of_bb() { |
| return sm_get_const_existing("[B", &const_arrayref_of_bb); |
| } |
| |
| //return SmConstant (known verification type) corresponding to char[] |
| //returned value is cached |
| SmConstant sm_get_const_arrayref_of_char() { |
| return sm_get_const_existing("[C", &const_arrayref_of_char); |
| } |
| |
| //return SmConstant (known verification type) corresponding to double[] |
| //returned value is cached |
| SmConstant sm_get_const_arrayref_of_double() { |
| return sm_get_const_existing("[D", &const_arrayref_of_double); |
| } |
| |
| //return SmConstant (known verification type) corresponding to float[] |
| //returned value is cached |
| SmConstant sm_get_const_arrayref_of_float() { |
| return sm_get_const_existing("[F", &const_arrayref_of_float); |
| } |
| |
| //return SmConstant (known verification type) corresponding to int[] |
| //returned value is cached |
| SmConstant sm_get_const_arrayref_of_integer() { |
| return sm_get_const_existing("[I", &const_arrayref_of_integer); |
| } |
| |
| //return SmConstant (known verification type) corresponding to long[] |
| //returned value is cached |
| SmConstant sm_get_const_arrayref_of_long() { |
| return sm_get_const_existing("[J", &const_arrayref_of_long); |
| } |
| |
| //return SmConstant (known verification type) corresponding to short[] |
| //returned value is cached |
| SmConstant sm_get_const_arrayref_of_short() { |
| return sm_get_const_existing("[S", &const_arrayref_of_short); |
| } |
| |
| //return SmConstant (known verification type) corresponding to Object[] |
| //returned value is cached |
| SmConstant sm_get_const_arrayref_of_object() { |
| return sm_get_const_existing("[Ljava/lang/Object;", &const_arrayref_of_object); |
| } |
| |
| //return SmConstant represented array of specified type |
| //the type is specified in the OP_NEWARRAY instruction. See the spec for possible types |
| SmConstant sm_get_const_arrayref(U_8 see_spec) { |
| switch ( see_spec ) { |
| case 4: //T_BOOLEAN |
| case 8: //T_BYTE |
| return sm_get_const_arrayref_of_bb(); |
| case 5: //T_CHAR |
| return sm_get_const_arrayref_of_char(); |
| case 6: //T_FLOAT |
| return sm_get_const_arrayref_of_float(); |
| case 7: //T_DOUBLE |
| return sm_get_const_arrayref_of_double(); |
| case 9: //T_SHORT |
| return sm_get_const_arrayref_of_short(); |
| case 10: //T_INT |
| return sm_get_const_arrayref_of_integer(); |
| case 11: //T_LONG |
| return sm_get_const_arrayref_of_long(); |
| } |
| assert(0); |
| return SM_BOGUS; |
| } |
| |
| //check if expected_ref is a super class of 'this', its package differs, and it's protected |
| enum FieldAndMethodCheck {_FALSE, _CLONE, _TRUE}; |
| int checkFieldAccess(SmConstant expected_ref, unsigned short method_idx); |
| int checkVirtualAccess(SmConstant expected_ref, unsigned short method_idx); |
| int checkSuperAndPackage(SmConstant expected_ref); |
| private: |
| //ref to the main class of the verifier |
| SharedClasswideData *classwide; |
| |
| //class handler of the class being verified |
| Class_Handle k_class; |
| |
| //constantpool length |
| unsigned k_cp_length; |
| |
| //hash table storing class names |
| vf_Hash hash; |
| vf_ValidType *validTypes; |
| unsigned tableIncr; |
| unsigned validTypesTableMax; |
| unsigned validTypesTableSz; |
| |
| /*****************/ |
| //cache for SmConstant constants; |
| SmConstant const_object, const_class, const_string, const_throwable, const_arrayref_of_bb, |
| const_arrayref_of_char, const_arrayref_of_double, const_arrayref_of_float, |
| const_arrayref_of_integer, const_arrayref_of_long, const_arrayref_of_short, |
| const_arrayref_of_object, const_this; |
| |
| |
| void NewConstraint(const char *available, const char *required); |
| |
| //Get next free table entry index. |
| //Reallocate table if out of free entries. |
| unsigned check_table() { |
| if( validTypesTableSz + 1 >= validTypesTableMax ) { |
| validTypesTableMax += tableIncr; |
| validTypes = (vf_ValidType*)tc_realloc(validTypes, sizeof(vf_ValidType) * validTypesTableMax); |
| } |
| return validTypesTableSz++; |
| } |
| |
| int is_bool_array_conv_needed(const char *type_name, int length); |
| |
| }; |
| |
| Class_Handle vf_resolve_class(Class_Handle k_class, const char* name, bool need_load); |
| int vf_is_extending(Class_Handle from, Class_Handle to); |
| |
| #endif |