📄 verify2.c
字号:
CLASS_CNAME(class)); return(false); } else if (CLASS_IS_FINAL(class)) { postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "interfaces cannot be final (in interface \"%s\")", CLASS_CNAME(class)); return(false); } }#endif /* UNENFORCED_INTERFACE_RESTRICTIONS */ { Field *fld; int lpc; fld = CLASS_FIELDS(class); for( lpc = 0; lpc < CLASS_NFIELDS(class); lpc++ ) { if( !checkField(&fld[lpc], einfo) ) return(false); } } /* java/lang/Object does not have a superclass, is not final, and is not an interface, * so we skip all of those checks */ if(strcmp(OBJECTCLASS, CLASS_CNAME(class))) { if (class->superclass == NULL) { /*********************************************************** * 1 - every class except java/lang/Object has a superclass ***********************************************************/ postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "class \"%s\" does not have a superclass", CLASS_CNAME(class)); return(false); } else if (CLASS_IS_FINAL(class->superclass)) { /********************************************************* * 2a: check that final classes are not inherited from *********************************************************/ postExceptionMessage(einfo, JAVA_LANG(VerifyError), "class \"%s\" cannot inherit from final class \"%s\"", CLASS_CNAME(class), CLASS_CNAME(class->superclass)); return(false); } else if (CLASS_IS_INTERFACE(class)) { /* we separate this from the rest of the method checking because the only requirement * of methods in an interface is that they be public, abstract, and nothing else. */ Method* method; int n; for (n = CLASS_NMETHODS(class), method = CLASS_METHODS(class); n > 0; --n, ++method) { /* if it's <clinit> (init_name) then it doesn't have to be public. * compilers often insert a <clinit> function to initialize an * interfaces public static fields, if there are any. */ if (strcmp(init_name->data, METHOD_NAMED(method))) { if (!METHOD_IS_PUBLIC(method)) { postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "interface methods must be declared public (method \"%s\" in interface \"%s\")", METHOD_NAMED(method), CLASS_CNAME(class)); return(false); } else if (!METHOD_IS_ABSTRACT(method)) { postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "interface methods must be declared abstract (method \"%s\" in interface \"%s\")", METHOD_NAMED(method), CLASS_CNAME(class)); return(false); } } if (checkMethodStaticConstraints(method, einfo) == false) { /* something else is wrong...exception raised elsewhere */ return(false); } } } else { /********************************************************* * 2b: check that final methods are not overridden *********************************************************/ Hjava_lang_Class *superclass; Method* curMethod; Method* method; int n, m; for (n = CLASS_NMETHODS(class), curMethod = CLASS_METHODS(class); n > 0; --n, ++curMethod) { /* check static constraints on each method */ if (METHOD_IS_CONSTRUCTOR(curMethod) && checkConstructor(curMethod, einfo) == false) { return(false); } else if (checkMethodStaticConstraints(curMethod, einfo) == false) { return(false); } } /* cycle through superclass hiarchy and make sure final methods aren't overriden */ for (superclass = class->superclass; superclass != NULL; superclass = superclass->superclass) { /* cycle through methods in current super class */ for (m = CLASS_NMETHODS(superclass), method = CLASS_METHODS(superclass); m > 0; --m, ++method) { if (METHOD_IS_FINAL(method) && !METHOD_IS_PRIVATE(method) && /* the following exceptions come from testing against Sun's JVM behavior */ (strcmp(init_name->data, METHOD_NAMED(method)) && strcmp("this", METHOD_NAMED(method)))) { /* make sure the method in question was not overriden in the current class */ for (n = CLASS_NMETHODS(class), curMethod = CLASS_METHODS(class); n > 0; --n, ++curMethod) { /* TODO: we should really put all the methods of class into a hash table * that we can access through name and signature. this would make * this check more efficient (is this done in the interpretter? if so * we may think about setting up the hashes here and just keeping them * around for later). */ if (utf8ConstEqual(curMethod->name, method->name) && utf8ConstEqual(METHOD_SIG(curMethod), METHOD_SIG(method))) { postExceptionMessage(einfo, JAVA_LANG(VerifyError), "final method \"%s\" declared in class \"%s\" is overriden in class \"%s\"", METHOD_NAMED(method), CLASS_CNAME(class->superclass), CLASS_CNAME(class)); return(false); } } } } } } } /********************************************************* * 3 - Check class constant pool is consistent * * This is the only section of pass 2 that was available * under Transvirtual, though even this has been modified. *********************************************************/ /* error message for step 3 */ pool = CLASS_CONSTANTS(class); /* Constant pool loaded - check it's integrity. */ for (idx = 1; idx < pool->size; idx++) { switch (pool->tags[idx]) { case CONSTANT_Fieldref: case CONSTANT_Methodref: case CONSTANT_InterfaceMethodref: tag = CONST_TAG(FIELDREF_CLASS(idx, pool), pool); if (tag != CONSTANT_Class && tag != CONSTANT_ResolvedClass) { return poolError(class, einfo); } if (CONST_TAG(FIELDREF_NAMEANDTYPE(idx, pool), pool) != CONSTANT_NameAndType) { return poolError(class, einfo); } break; case CONSTANT_NameAndType: if (CONST_TAG(NAMEANDTYPE_NAME(idx, pool), pool) != CONSTANT_Utf8) { return poolError(class, einfo); } if (CONST_TAG(NAMEANDTYPE_SIGNATURE(idx, pool), pool) != CONSTANT_Utf8) { return poolError(class, einfo); } break; /* the following tags are always legal, so no furthur checks need be performed */ case CONSTANT_Long: case CONSTANT_Double: idx++; case CONSTANT_Integer: case CONSTANT_Float: case CONSTANT_Utf8: case CONSTANT_ResolvedString: case CONSTANT_ResolvedClass: /* CONSTANT_Class and CONSTANT_String * have already been re-written to avoid the * extra indirection added by Java. This is to fit * with the precompiled format. Here we will not * get an error. */ case CONSTANT_Class: case CONSTANT_String: break; default: /* undefined tag */ return poolError(class, einfo); break; } } DBG(VERIFY2, printConstantPool(class)); /************************************************************** * 4 - ensure that all field and method references in * constant pool have valid names, classes, and type * descriptor * * From the JVM spec pp.141-2: * Note that when it looks at field and method references, * this pass does not check to make sure that the given * field or method actually exists in the given class, nor * does it check that the type descriptors given refer to * real classes. It checks only that these items are well * formed. **************************************************************/ /* Constant pool loaded - check the integrity of the type references */ pool = CLASS_CONSTANTS(class); for (idx = 1; idx < pool->size; idx++) { switch (pool->tags[idx]) { case CONSTANT_Long: case CONSTANT_Double: idx++; case CONSTANT_Integer: case CONSTANT_Float: case CONSTANT_Utf8: case CONSTANT_ResolvedString: case CONSTANT_ResolvedClass: case CONSTANT_Class: case CONSTANT_String: case CONSTANT_NameAndType: break; case CONSTANT_Fieldref: if (!parseFieldTypeDescriptor(FIELDREF_SIGD(idx, pool))) { postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "malformed field reference type descriptor, \"%s\", in class \"%s\"", CONST_UTF2CHAR(FIELDREF_TYPE(idx, pool), pool), CLASS_CNAME(class)); return(false); } break; case CONSTANT_Methodref: if (!parseMethodTypeDescriptor(METHODREF_SIGD(idx, pool))) { postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "malformed method reference type descriptor, \"%s\", in class \"%s\"", CONST_UTF2CHAR(METHODREF_SIGNATURE(idx, pool), pool), CLASS_CNAME(class)); return(false); } break; case CONSTANT_InterfaceMethodref: if (!parseMethodTypeDescriptor(INTERFACEMETHODREF_SIGD(idx, pool))) { postExceptionMessage(einfo, JAVA_LANG(ClassFormatError), "malformed interface method reference type descriptor, \"%s\", in class \"%s\"", CONST_UTF2CHAR(INTERFACEMETHODREF_SIGNATURE(idx, pool), pool), CLASS_CNAME(class)); return(false); } break; default: /* we'll never get here, because of pass 3 */ postExceptionMessage(einfo, JAVA_LANG(InternalError), "step 4 of pass 2 verification has screwed up while processing class \"%s\"", CLASS_CNAME(class)); return(false); } } return (true);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -