diff --git a/vm/vmcore/src/verifier/Graph.cpp b/vm/vmcore/src/verifier/Graph.cpp index 96e76f7..11eedbc 100644 --- a/vm/vmcore/src/verifier/Graph.cpp +++ b/vm/vmcore/src/verifier/Graph.cpp @@ -34,8 +34,7 @@ vf_Graph::DumpGraph() { #if _VF_DEBUG VF_DEBUG( "Method: " << class_get_name( m_ctx->m_class ) << "::" - << method_get_name( m_ctx->m_method ) - << method_get_descriptor( m_ctx->m_method ) << endl ); + << m_ctx->m_name << m_ctx->m_descriptor << endl ); VF_DEBUG( "-- start --" ); ResetNodeIterator(); while( HasMoreElements() ) { @@ -120,14 +119,12 @@ #if _VF_DEBUG // get class and method name const char *class_name = class_get_name( m_ctx->m_class ); - const char *method_name = method_get_name( m_ctx->m_method ); - const char *method_desc = method_get_descriptor( m_ctx->m_method ); // create file name - size_t len = strlen( class_name ) + strlen( method_name ) - + strlen( method_desc ) + 6; + size_t len = strlen( class_name ) + strlen( m_ctx->m_name ) + + strlen( m_ctx->m_descriptor ) + 6; char *fname = (char*)STD_ALLOCA( len ); - sprintf( fname, "%s_%s%s", class_name, method_name, method_desc ); + sprintf( fname, "%s_%s%s", class_name, m_ctx->m_name, m_ctx->m_descriptor ); char *f_start; char *pointer; @@ -168,7 +165,7 @@ #if _VF_DEBUG return; } // create name of graph - sprintf( fname, "%s.%s%s", class_name, method_name, method_desc ); + sprintf( fname, "%s.%s%s", class_name, m_ctx->m_name, m_ctx->m_descriptor ); // print graph to file DumpDotHeader( f_start, fout ); diff --git a/vm/vmcore/src/verifier/Verifier.cpp b/vm/vmcore/src/verifier/Verifier.cpp index e9123f4..e639b92 100644 --- a/vm/vmcore/src/verifier/Verifier.cpp +++ b/vm/vmcore/src/verifier/Verifier.cpp @@ -90,27 +90,20 @@ #endif // _VF_DEBUG static vf_Result vf_verify_method_bytecode( vf_Context *ctx ) // verification context { - vf_Result result = VER_OK; - VF_TRACE( "method", VF_REPORT_CTX( ctx ) << "verifying method" ); - /** - * Set method for type pool - */ - ctx->m_type->SetMethod( ctx->m_method ); - - // get method signature - const char *descr = method_get_descriptor( ctx->m_method ); + // set method for type pool + ctx->m_type->SetMethod( ctx ); - // parse method signature - vf_parse_description( descr, &ctx->m_method_inlen, + // parse method descriptor + vf_parse_description( ctx->m_descriptor, &ctx->m_method_inlen, &ctx->m_method_outlen ); - vf_set_description_vector( descr, ctx->m_method_inlen, 0, + vf_set_description_vector( ctx->m_descriptor, ctx->m_method_inlen, 0, ctx->m_method_outlen, &ctx->m_method_invector, &ctx->m_method_outvector, ctx ); // parse bytecode, fill instruction instr - result = vf_parse_bytecode( ctx ); + vf_Result result = vf_parse_bytecode( ctx ); if( VER_OK != result ) { goto labelEnd_verifyClassBytecode; } @@ -4893,8 +4886,7 @@ vf_dump_bytecode( vf_ContextHandle ctx ) VF_DEBUG ( "======================== VERIFIER METHOD DUMP ========================" ); VF_DEBUG( "Method: " << class_get_name( ctx->m_class ) - << "." << method_get_name( ctx->m_method ) - << method_get_descriptor( ctx->m_method ) << endl ); + << "." << ctx->m_name << ctx->m_descriptor << endl ); VF_DEBUG( "0 [-]: -> START-ENTRY" ); unsigned short handler_count = ctx->m_handlers; diff --git a/vm/vmcore/src/verifier/ver_dataflow.cpp b/vm/vmcore/src/verifier/ver_dataflow.cpp old mode 100644 new mode 100755 index c51d9df..be9e1df --- a/vm/vmcore/src/verifier/ver_dataflow.cpp +++ b/vm/vmcore/src/verifier/ver_dataflow.cpp @@ -78,6 +78,9 @@ vf_dump_vector_entry( vf_MapEntry *entry *stream << " [THIS]"; } break; + case SM_RETURN_ADDR: + *stream << " [RT " << entry->m_pc % 10 << "]"; + break; case SM_ANY: *stream << " [ANY ]"; break; @@ -834,6 +837,7 @@ vf_check_instruction_in_vector( vf_MapEn << entry->m_local ); } if( !ctx->m_error ) { + result = vf_check_entry_refs( entry, vector, local_init, ctx ); VF_REPORT( ctx, "Data flow analysis error" ); } return result; @@ -1030,10 +1034,10 @@ vf_set_node_out_vector( vf_NodeHandle no } VF_DUMP( DUMP_INSTR_MAP, { // dump instruction OUT vector - cerr << "-------------- instruction #" << ( instr - - node-> - m_start ) << - ", node #" << node->m_nodecount << " out: " << endl; + cerr << "-------------- instruction #" + << ( instr - node->m_start ) + << ", node #" << ctx->m_graph->GetNodeNum(node) + << " out: " << endl; vf_dump_vector( invector, instr, &cerr );} ); } @@ -1068,8 +1072,8 @@ vf_create_node_vectors( vf_NodeHandle no VF_DUMP( DUMP_NODE_MAP, { // dump node number - cerr << endl << "-------------- Node #" << node-> - m_nodecount << endl; + cerr << endl << "-------------- Node #" + << ctx->m_graph->GetNodeNum(node) << endl; // dump in vector cerr << "IN vector :" << endl; vf_dump_vector( incoming, NULL, &cerr );} ); @@ -1095,8 +1099,9 @@ vf_create_node_vectors( vf_NodeHandle no } VF_DUMP( DUMP_NODE_MAP, { // dump out vector - cerr << "-------------- Node #" << node->m_nodecount - << endl << "OUT vector:" << endl; + cerr << "-------------- Node #" + << ctx->m_graph->GetNodeNum(node) + << endl << "OUT vector:" << endl; vf_dump_vector( outcoming, NULL, &cerr );} ); @@ -1193,7 +1198,7 @@ vf_check_node_data_flow( vf_NodeHandle n VF_DUMP( DUMP_MERGE_MAP, if( is_changed ) { // dump out vectors cerr << "============== merge IN vector for Node #" - << outnode->m_nodecount << endl; + << ctx->m_graph->GetNodeNum(outnode) << endl; cerr << "IN vectors:" << endl; cerr << "1: --------------" << endl; vf_dump_vector( incoming, NULL, &cerr ); @@ -1203,7 +1208,8 @@ vf_check_node_data_flow( vf_NodeHandle n cerr << "result: --------------" << endl; vf_dump_vector( outnode_vector, NULL, &cerr ); cerr << "### Recount from " << *node_count - << " (now " << node->m_nodecount << ")" << endl;} + << " (now " << ctx->m_graph->GetNodeNum(node) + << ")" << endl;} ); } } diff --git a/vm/vmcore/src/verifier/ver_real.h b/vm/vmcore/src/verifier/ver_real.h index d0d7a3a..361358c 100644 --- a/vm/vmcore/src/verifier/ver_real.h +++ b/vm/vmcore/src/verifier/ver_real.h @@ -109,9 +109,10 @@ #define VF_SET_CTX( ctx, error_message ) } /** Dump a current class and method. */ -#define VF_REPORT_CTX( ctx ) "(class: " << class_get_name( (ctx)->m_class ) \ - << ", method: " << method_get_name( (ctx)->m_method ) \ - << method_get_descriptor( (ctx)->m_method ) << ") " +#define VF_REPORT_CTX( ctx ) \ + "(class: " << class_get_name( (ctx)->m_class ) \ + << ", method: " << (ctx)->m_name << (ctx)->m_descriptor \ + << ") " /** Report a verification error. */ #define VF_REPORT( ctx, error_message ) \ @@ -682,12 +683,14 @@ struct vf_Hash */ struct vf_TypeConstraint { - const char *m_source; ///< constraint source class name - const char *m_target; ///< constraint target class name - method_handler m_method; ///< constraint for method - vf_TypeConstraint *m_next; ///< next constraint - unsigned short m_index; ///< constant pool index - unsigned short m_check_type; ///< constraint check type @see vf_CheckConstraint + const char *m_source; ///< constraint source class name + const char *m_target; ///< constraint target class name + method_handler m_method; ///< constraint for method + const char *m_name; ///< constraint method name + const char *m_descriptor; ///< constraint method descriptor + vf_TypeConstraint *m_next; ///< next constraint + unsigned short m_index; ///< constant pool index + unsigned short m_check_type; ///< constraint check type @see vf_CheckConstraint }; /** @@ -706,7 +709,7 @@ struct vf_TypePool * Type constraint collection destructor. * @note Function release memory for collection memory pool and hash table. */ - ~vf_TypePool (); + ~vf_TypePool (); /** * Function creates valid type which is identical to given class. @@ -767,9 +770,9 @@ struct vf_TypePool /** * Sets current context method. - * @param method - current context method + * @param ctx - current verifier context */ - void SetMethod( method_handler method ); + void SetMethod( vf_ContextHandle ctx ); /** * Sets restriction from target class to source class. @@ -788,6 +791,8 @@ struct vf_TypePool vf_Pool *m_pool; ///< collection memory pool vf_Hash *m_Hash; ///< hash table method_handler m_method; ///< current context method + const char *m_name; ///< current context method name + const char *m_descriptor; ///< current context method descriptor vf_TypeConstraint *m_restriction; ///< array of the class constraints }; // vf_TypePool @@ -807,8 +812,9 @@ struct vf_Context * Verifier context constructor */ vf_Context ():m_class( NULL ), m_type( NULL ), m_error( NULL ), - m_method( NULL ), m_graph( NULL ), m_pool( NULL ), m_instr( NULL ), - m_last_instr( NULL ), m_retnum( 0 ), m_verify_all( false ) + m_method( NULL ), m_name(NULL), m_descriptor(NULL), m_graph( NULL ), + m_pool( NULL ), m_instr( NULL ), m_last_instr( NULL ), m_retnum( 0 ), + m_verify_all( false ) { vf_ContextVType zero2 = { 0 }; m_vtype = zero2; @@ -816,7 +822,10 @@ struct vf_Context void SetMethod( method_handler method ) { + assert(method); m_method = method; + m_name = method_get_name(method); + m_descriptor = method_get_descriptor(method); // get method parameters m_len = method_get_code_length( method ); @@ -828,8 +837,7 @@ struct vf_Context m_maxstack = method_get_max_stack( method ); // cache in the context if the method is a constructor - m_is_constructor = - memcmp( method_get_name( method ), "", 7 ) == 0; + m_is_constructor = (memcmp( m_name, "", 7 ) == 0); } /** @@ -851,6 +859,8 @@ struct vf_Context void ClearContext() { m_method = NULL; + m_name = NULL; + m_descriptor = NULL; m_is_constructor = false; m_graph = NULL; m_instr = NULL; @@ -871,29 +881,32 @@ struct vf_Context vf_BCode *m_bc; ///< bytecode to instruction mapping unsigned m_retnum; ///< a number of rets - /** - * Cached method info. - */ + // Cached method info. class_handler m_class; ///< a context class method_handler m_method; ///< a context method + const char *m_name; ///< a context method name + const char *m_descriptor; ///< a context method descriptor unsigned m_len; ///< bytecode length unsigned char *m_bytes; ///< bytecode location unsigned short m_handlers; ///< a number of exception handlers unsigned short m_maxstack; ///< max stack length unsigned short m_maxlocal; ///< max local number bool m_is_constructor; ///< true if the - ///< method is a constructor + ///< method is a constructor - vf_SubContext *m_sub_ctx; ///< aggregate subroutine info - vf_MapVector *m_map; ///< a stack map for control flow analysis, - ///< vectors themselves are allocated from the graph pool + // Subrotine info + vf_SubContext *m_sub_ctx; ///< aggregate subroutine info + vf_MapVector *m_map; ///< a stack map for control flow + ///< analysis, vectors themselves are + ///< allocated from the graph pool vf_MapEntry *m_method_invector; ///< method parameters unsigned short m_method_inlen; ///< a length of m_method_invector vf_MapEntry *m_method_outvector; ///< method return value unsigned short m_method_outlen; ///< a length of m_method_outvector + // Data flow analisys info vf_MapEntry *m_buf; ///< used to store intermediate stack states - ///< during data flow analysis + ///< during data flow analysis bool m_verify_all; ///< if true need to verify more checks @@ -902,11 +915,11 @@ struct vf_Context */ struct vf_ContextVType { - vf_ValidType *m_class; ///< a given class + vf_ValidType *m_class; ///< a given class vf_ValidType *m_throwable; ///< java/lang/Throwable - vf_ValidType *m_object; ///< java/lang/Object - vf_ValidType *m_array; ///< [Ljava/lang/Object; - vf_ValidType *m_clone; ///< java/lang/Cloneable + vf_ValidType *m_object; ///< java/lang/Object + vf_ValidType *m_array; ///< [Ljava/lang/Object; + vf_ValidType *m_clone; ///< java/lang/Cloneable vf_ValidType *m_serialize; ///< java/io/Serializable } m_vtype; diff --git a/vm/vmcore/src/verifier/ver_subroutine.cpp b/vm/vmcore/src/verifier/ver_subroutine.cpp index 2a0d2dc..1f0d7c7 100644 --- a/vm/vmcore/src/verifier/ver_subroutine.cpp +++ b/vm/vmcore/src/verifier/ver_subroutine.cpp @@ -134,15 +134,24 @@ static inline vf_Result ResolveSubroutin unsigned index; for (index = 0; index < map->m_number; index++) { map->m_local[index].m_type = SM_ANY; + map->m_local[index].m_is_local = true; + map->m_local[index].m_local = index; } map->m_depth = p_element->m_node->m_inmap.m_depth; + // FIXME - stack depth should be greater then 0 + // assert(map->m_depth); for (index = 0; index + 1 < map->m_depth; index++) { map->m_stack[index].m_type = SM_ANY; } map->m_stack[index].m_type = SM_RETURN_ADDR; - map->m_stack[index].m_pc = + map->m_stack[index++].m_pc = (unsigned) (p_element->m_node->m_start->m_addr - ctx->m_bytes); + // FIXME - index should be equal to stack depth + // assert(index == map->m_depth); + for (; index < ctx->m_maxstack; index++) { + map->m_stack[index].m_type = SM_TOP; + } } VF_DUMP(DUMP_NODESTACK, DumpNodeStack(ctx)); diff --git a/vm/vmcore/src/verifier/ver_utils.cpp b/vm/vmcore/src/verifier/ver_utils.cpp index 96cab5f..ef96b04 100644 --- a/vm/vmcore/src/verifier/ver_utils.cpp +++ b/vm/vmcore/src/verifier/ver_utils.cpp @@ -230,8 +230,8 @@ inline vf_HashEntry *vf_Hash::NewHashEnt /** * Type constraint collection constructor. */ -vf_TypePool::vf_TypePool ():m_method( NULL ), -m_restriction( NULL ) +vf_TypePool::vf_TypePool () + : m_method( NULL ), m_name(NULL), m_descriptor(NULL), m_restriction(NULL) { m_pool = vf_create_pool(); m_Hash = new vf_Hash ( m_pool ); @@ -334,11 +334,10 @@ void vf_TypePool::DumpTypeConstraints( o for( vf_TypeConstraint *constraint = m_restriction; constraint; constraint = constraint->m_next ) { *out << "CONSTRAINT: have \"" - << constraint->m_source << "\" need \"" << constraint-> - m_target << "\" for method " << - class_get_name( method_get_class( m_method ) ) << "." << - method_get_name( m_method ) << method_get_descriptor( m_method ) - << endl; + << constraint->m_source << "\" need \"" + << constraint->m_target << "\" for method " + << class_get_name( method_get_class( m_method ) ) << "." + << m_name << m_descriptor << endl; } } // vf_TypePool::DumpTypeConstraints @@ -353,10 +352,12 @@ inline vf_TypeConstraint *vf_TypePool::G /** * Sets current context method. */ -void vf_TypePool::SetMethod( method_handler method ) +void vf_TypePool::SetMethod( vf_ContextHandle ctx ) { - // set method - m_method = method; + // set method context + m_method = ctx->m_method; + m_name = ctx->m_name; + m_descriptor = ctx->m_descriptor; } // vf_TypePool::SetMethod /** @@ -390,24 +391,24 @@ void vf_TypePool::SetRestriction( const restriction->m_index = index; restriction->m_check_type = check_type; restriction->m_method = m_method; + restriction->m_name = m_name; + restriction->m_descriptor = m_descriptor; restriction->m_next = m_restriction; m_restriction = restriction; // trace restriction if( index ) { VF_TRACE( "constraint", "CONSTRAINT: for class \"" - << class_get_name( method_get_class( m_method ) ) << - "\" CP index #" << index << " check access: have \"" << - source << "\" need \"" << target << "\" for method " << - class_get_name( method_get_class( m_method ) ) << "." << - method_get_name( m_method ) << - method_get_descriptor( m_method ) ); + << class_get_name( method_get_class( m_method ) ) + << "\" CP index #" << index << " check access: have \"" + << source << "\" need \"" << target << "\" for method " + << class_get_name( method_get_class( m_method ) ) << "." + << m_name << m_descriptor ); } else { VF_TRACE( "constraint", "CONSTRAINT: have \"" << source << "\" need \"" << target << "\" for method " << class_get_name( method_get_class( m_method ) ) << "." - << method_get_name( m_method ) << - method_get_descriptor( m_method ) ); + << m_name << m_descriptor ); } } // vf_TypePool::SetRestriction @@ -631,7 +632,10 @@ vf_set_class_constraint( vf_TypeConstrai // create entry in string pool for checked class hash_entry = hash->NewHashEntry( restriction->m_source ); constraint->m_source = hash_entry->key; - constraint->m_method = restriction->m_method; + // set only method name and descriptor due to + // method handle could be changed during class preparation phase + constraint->m_name = restriction->m_name; + constraint->m_descriptor = restriction->m_descriptor; constraint->m_check_type = restriction->m_check_type; constraint->m_next = save_collection; save_collection = constraint; @@ -1227,10 +1231,8 @@ vf_check_access_constraint( const char * if( !field ) { // NoSuchFieldError or IllegalAccessError - nothing to check VF_DEBUG( "verifying class " << class_get_name( ctx->m_class ) - << " (method " << method_get_name( ctx->m_method ) - << method_get_descriptor( ctx->m_method ) - << - ") couldn't resolve field with constant pool index #" + << " (method " << ctx->m_name << ctx->m_descriptor + << ") couldn't resolve field with constant pool index #" << index ); return VER_OK; } @@ -1242,10 +1244,8 @@ vf_check_access_constraint( const char * if( !method || method_is_static( method ) ) { // NoSuchMethodError or IllegalAccessError - nothing to check VF_DEBUG( "verifying class " << class_get_name( ctx->m_class ) - << " (method " << method_get_name( ctx->m_method ) - << method_get_descriptor( ctx->m_method ) - << - ") couldn't resolve method with constant pool index #" + << " (method " << ctx->m_name << ctx->m_descriptor + << ") couldn't resolve method with constant pool index #" << index ); return VER_OK; } @@ -1292,7 +1292,8 @@ vf_check_class_constraints( vf_Context * for( vf_TypeConstraint *constraint = collection; constraint; constraint = constraint->m_next ) { // set context method - ctx->SetMethod( constraint->m_method ); + // FIXME - need set method to context? + //ctx->SetMethod( constraint->m_method ); // check constraint vf_Result result = vf_check_constraint( constraint, ctx ); @@ -1307,6 +1308,10 @@ vf_check_class_constraints( vf_Context * // return error return result; } else { + // these constraints should be checked at the first time + assert(constraint->m_check_type != VF_CHECK_ACCESS_FIELD); + assert(constraint->m_check_type != VF_CHECK_ACCESS_METHOD); + // set the last constraint last = constraint; } @@ -1340,9 +1345,8 @@ vf_force_check_constraint( vf_TypeConstr vf_resolve_class( constraint->m_target, true, ctx ); if( !target ) { VF_DEBUG( "verifying class " << class_get_name( ctx->m_class ) - << " (method " << method_get_name( constraint->m_method ) - << method_get_descriptor( constraint->m_method ) - << ") couldn't load class \"" + << " (method " << constraint->m_name + << constraint->m_descriptor << ") couldn't load class \"" << ( ( constraint->m_target[0] == 'L' ) ? &( constraint->m_target[1] ) : constraint->m_target ) << "\"" ); @@ -1391,9 +1395,8 @@ vf_force_check_constraint( vf_TypeConstr vf_resolve_class( constraint->m_source, true, ctx ); if( !source ) { VF_DEBUG( "verifying class " << class_get_name( ctx->m_class ) - << " (method " << method_get_name( constraint->m_method ) - << method_get_descriptor( constraint->m_method ) - << ") couldn't load class \"" + << " (method " << constraint->m_name + << constraint->m_descriptor << ") couldn't load class \"" << ( ( constraint->m_source[0] == 'L' ) ? &( constraint->m_source[1] ) : constraint->m_source ) << "\"" ); @@ -1422,6 +1425,8 @@ vf_force_check_constraint( vf_TypeConstr if( !vf_is_valid( source, target, ctx->m_class, check ) ) { // return error ctx->m_method = constraint->m_method; + ctx->m_name = constraint->m_name; + ctx->m_descriptor = constraint->m_descriptor; vf_set_error( check, ctx ); return VER_ErrorIncompatibleArgument; }