📄 pass3averifier.java
字号:
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 + -