📄 pass3averifier.java
字号:
if (idx > maxminus1){ constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitASTORE(ASTORE o){ int idx = o.getIndex(); if (idx < 0){ constraintViolated(o, "Index '"+idx+"' must be non-negative."); } else{ int maxminus1 = max_locals()-1; if (idx > maxminus1){ constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitIINC(IINC o){ int idx = o.getIndex(); if (idx < 0){ constraintViolated(o, "Index '"+idx+"' must be non-negative."); } else{ int maxminus1 = max_locals()-1; if (idx > maxminus1){ constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitRET(RET o){ int idx = o.getIndex(); if (idx < 0){ constraintViolated(o, "Index '"+idx+"' must be non-negative."); } else{ int maxminus1 = max_locals()-1; if (idx > maxminus1){ constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-1 '"+maxminus1+"'."); } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitLLOAD(LLOAD o){ int idx = o.getIndex(); if (idx < 0){ constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]"); } else{ int maxminus2 = max_locals()-2; if (idx > maxminus2){ constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'."); } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitDLOAD(DLOAD o){ int idx = o.getIndex(); if (idx < 0){ constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]"); } else{ int maxminus2 = max_locals()-2; if (idx > maxminus2){ constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'."); } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitLSTORE(LSTORE o){ int idx = o.getIndex(); if (idx < 0){ constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]"); } else{ int maxminus2 = max_locals()-2; if (idx > maxminus2){ constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'."); } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitDSTORE(DSTORE o){ int idx = o.getIndex(); if (idx < 0){ constraintViolated(o, "Index '"+idx+"' must be non-negative. [Constraint by JustIce as an analogon to the single-slot xLOAD/xSTORE instructions; may not happen anyway.]"); } else{ int maxminus2 = max_locals()-2; if (idx > maxminus2){ constraintViolated(o, "Index '"+idx+"' must not be greater than max_locals-2 '"+maxminus2+"'."); } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitLOOKUPSWITCH(LOOKUPSWITCH o){ int[] matchs = o.getMatchs(); int max = Integer.MIN_VALUE; for (int i=0; i<matchs.length; i++){ if (matchs[i] == max && i != 0){ constraintViolated(o, "Match '"+matchs[i]+"' occurs more than once."); } if (matchs[i] < max){ constraintViolated(o, "Lookup table must be sorted but isn't."); } else{ max = matchs[i]; } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitTABLESWITCH(TABLESWITCH o){ // "high" must be >= "low". We cannot check this, as BCEL hides // it from us. } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitPUTSTATIC(PUTSTATIC o){ String field_name = o.getFieldName(cpg); JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName()); Field[] fields = jc.getFields(); Field f = null; for (int i=0; i<fields.length; i++){ if (fields[i].getName().equals(field_name)){ f = fields[i]; break; } } if (f == null){ throw new AssertionViolatedException("Field not found?!?"); } if (f.isFinal()){ if (!(myOwner.getClassName().equals(o.getClassType(cpg).getClassName()))){ constraintViolated(o, "Referenced field '"+f+"' is final and must therefore be declared in the current class '"+myOwner.getClassName()+"' which is not the case: it is declared in '"+o.getClassType(cpg).getClassName()+"'."); } } if (! (f.isStatic())){ constraintViolated(o, "Referenced field '"+f+"' is not static which it should be."); } String meth_name = Repository.lookupClass(myOwner.getClassName()).getMethods()[method_no].getName(); // If it's an interface, it can be set only in <clinit>. if ((!(jc.isClass())) && (!(meth_name.equals(Constants.STATIC_INITIALIZER_NAME)))){ constraintViolated(o, "Interface field '"+f+"' must be set in a '"+Constants.STATIC_INITIALIZER_NAME+"' method."); } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitGETSTATIC(GETSTATIC o){ String field_name = o.getFieldName(cpg); JavaClass jc = Repository.lookupClass(o.getClassType(cpg).getClassName()); Field[] fields = jc.getFields(); Field f = null; for (int i=0; i<fields.length; i++){ if (fields[i].getName().equals(field_name)){ f = fields[i]; break; } } if (f == null){ throw new AssertionViolatedException("Field not found?!?"); } if (! (f.isStatic())){ constraintViolated(o, "Referenced field '"+f+"' is not static which it should be."); } } /* Checks if the constraints of operands of the said instruction(s) are satisfied. */ //public void visitPUTFIELD(PUTFIELD o){ // for performance reasons done in Pass 3b //} /* Checks if the constraints of operands of the said instruction(s) are satisfied. */ //public void visitGETFIELD(GETFIELD o){ // for performance reasons done in Pass 3b //} /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitINVOKEINTERFACE(INVOKEINTERFACE o){ // INVOKEINTERFACE is a LoadClass; the Class where the referenced method is declared in, // is therefore resolved/verified. // INVOKEINTERFACE is an InvokeInstruction, the argument and return types are resolved/verified, // too. So are the allowed method names. String classname = o.getClassName(cpg); JavaClass jc = Repository.lookupClass(classname); Method[] ms = jc.getMethods(); Method m = null; for (int i=0; i<ms.length; i++){ if ( (ms[i].getName().equals(o.getMethodName(cpg))) && (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) && (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){ m = ms[i]; break; } } if (m == null){ constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verfier does allow the method to be declared in some superinterface, which the Java Virtual Machine Specification, Second Edition does not."); } if (jc.isClass()){ constraintViolated(o, "Referenced class '"+jc.getClassName()+"' is a class, but not an interface as expected."); } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitINVOKESPECIAL(INVOKESPECIAL o){ // INVOKESPECIAL is a LoadClass; the Class where the referenced method is declared in, // is therefore resolved/verified. // INVOKESPECIAL is an InvokeInstruction, the argument and return types are resolved/verified, // too. So are the allowed method names. String classname = o.getClassName(cpg); JavaClass jc = Repository.lookupClass(classname); Method[] ms = jc.getMethods(); Method m = null; for (int i=0; i<ms.length; i++){ if ( (ms[i].getName().equals(o.getMethodName(cpg))) && (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) && (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){ m = ms[i]; break; } } if (m == null){ constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verfier does allow the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not."); } JavaClass current = Repository.lookupClass(myOwner.getClassName()); if (current.isSuper()){ if ((Repository.instanceOf( current, jc )) && (!current.equals(jc))){ if (! (o.getMethodName(cpg).equals(Constants.CONSTRUCTOR_NAME) )){ // Special lookup procedure for ACC_SUPER classes. int supidx = -1; Method meth = null; while (supidx != 0){ supidx = current.getSuperclassNameIndex(); current = Repository.lookupClass(current.getSuperclassName()); Method[] meths = current.getMethods(); for (int i=0; i<meths.length; i++){ if ( (meths[i].getName().equals(o.getMethodName(cpg))) && (Type.getReturnType(meths[i].getSignature()).equals(o.getReturnType(cpg))) && (objarrayequals(Type.getArgumentTypes(meths[i].getSignature()), o.getArgumentTypes(cpg))) ){ meth = meths[i]; break; } } if (meth != null) break; } if (meth == null){ constraintViolated(o, "ACC_SUPER special lookup procedure not successful: method '"+o.getMethodName(cpg)+"' with proper signature not declared in superclass hierarchy."); } } } } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitINVOKESTATIC(INVOKESTATIC o){ // INVOKESTATIC is a LoadClass; the Class where the referenced method is declared in, // is therefore resolved/verified. // INVOKESTATIC is an InvokeInstruction, the argument and return types are resolved/verified, // too. So are the allowed method names. String classname = o.getClassName(cpg); JavaClass jc = Repository.lookupClass(classname); Method[] ms = jc.getMethods(); Method m = null; for (int i=0; i<ms.length; i++){ if ( (ms[i].getName().equals(o.getMethodName(cpg))) && (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) && (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){ m = ms[i]; break; } } if (m == null){ constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verifier possibly allows the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not."); } if (! (m.isStatic())){ // implies it's not abstract, verified in pass 2. constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' has ACC_STATIC unset."); } } /** Checks if the constraints of operands of the said instruction(s) are satisfied. */ public void visitINVOKEVIRTUAL(INVOKEVIRTUAL o){ // INVOKEVIRTUAL is a LoadClass; the Class where the referenced method is declared in, // is therefore resolved/verified. // INVOKEVIRTUAL is an InvokeInstruction, the argument and return types are resolved/verified, // too. So are the allowed method names. String classname = o.getClassName(cpg); JavaClass jc = Repository.lookupClass(classname); Method[] ms = jc.getMethods(); Method m = null; for (int i=0; i<ms.length; i++){ if ( (ms[i].getName().equals(o.getMethodName(cpg))) && (Type.getReturnType(ms[i].getSignature()).equals(o.getReturnType(cpg))) && (objarrayequals(Type.getArgumentTypes(ms[i].getSignature()), o.getArgumentTypes(cpg))) ){ m = ms[i]; break; } } if (m == null){ constraintViolated(o, "Referenced method '"+o.getMethodName(cpg)+"' with expected signature not found in class '"+jc.getClassName()+"'. The native verfier does allow the method to be declared in some superclass or implemented interface, which the Java Virtual Machine Specification, Second Edition does not."); } if (! (jc.isClass())){ constraintViolated(o, "Referenced class '"+jc.getClassName()+"' is an interface, but not a class as expected."); } } // WIDE stuff is BCEL-internal and cannot be checked here. /** * A utility method like equals(Object) for arrays. * The equality of the elements is based on their equals(Object) * method instead of their object identity. */ private boolean objarrayequals(Object[] o, Object[] p){ if (o.length != p.length){ return false; } for (int i=0; i<o.length; i++){ if (! (o[i].equals(p[i])) ){ return false; } } return true; } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -