Code with Finding: |
class InstConstraintVisitor {
/**
* Ensures the specific preconditions of the said instruction.
*/
@Override
public void visitGETFIELD(GETFIELD o){
try {
Type objectref = stack().peek();
if (! ( (objectref instanceof ObjectType) || (objectref == Type.NULL) ) ){
constraintViolated(o, "Stack top should be an object reference that's not an array reference, but is '"+objectref+"'.");
}
String field_name = o.getFieldName(cpg);
JavaClass jc = Repository.lookupClass(getObjectType(o).getClassName());
Field[] fields = jc.getFields();
Field f = null;
for (Field field : fields) {
if (field.getName().equals(field_name)){
Type f_type = Type.getType(field.getSignature());
Type o_type = o.getType(cpg);
/* TODO: Check if assignment compatibility is sufficient.
* What does Sun do?
*/
if (f_type.equals(o_type)){
f = field;
break;
}
}
}
if (f == null){
JavaClass[] superclasses = jc.getSuperClasses();
outer:
for (JavaClass superclass : superclasses) {
fields = superclass.getFields();
for (Field field : fields) {
if (field.getName().equals(field_name)) {
Type f_type = Type.getType(field.getSignature());
Type o_type = o.getType(cpg);
if (f_type.equals(o_type)) {
f = field;
if ((f.getAccessFlags() & (Const.ACC_PUBLIC | Const.ACC_PROTECTED)) == 0) {
f = null;
}
break outer;
}
}
}
}
if (f == null) {
throw new AssertionViolatedException("Field '" + field_name + "' not found in " + jc.getClassName());
}
}
if (f.isProtected()){
ObjectType classtype = getObjectType(o);
ObjectType curr = ObjectType.getInstance(mg.getClassName());
if ( classtype.equals(curr) ||
curr.subclassOf(classtype) ){
Type t = stack().peek();
if (t == Type.NULL){
return;
}
if (! (t instanceof ObjectType) ){
constraintViolated(o, "The 'objectref' must refer to an object that's not an array. Found instead: '"+t+"'.");
}
ObjectType objreftype = (ObjectType) t;
if (! ( objreftype.equals(curr) ||
objreftype.subclassOf(curr) ) ){
//TODO: One day move to Staerk-et-al's "Set of object types" instead of "wider" object types
// created during the verification.
// "Wider" object types don't allow us to check for things like that below.
//constraintViolated(o, "The referenced field has the ACC_PROTECTED modifier, "+
// "and it's a member of the current class or a superclass of the current class."+
// " However, the referenced object type '"+stack().peek()+
// "' is not the current class or a subclass of the current class.");
}
}
}
// TODO: Could go into Pass 3a.
if (f.isStatic()){
constraintViolated(o, "Referenced field '"+f+"' is static which it shouldn't be.");
}
} catch (ClassNotFoundException e) {
// FIXME: maybe not the best way to handle this
throw new AssertionViolatedException("Missing class: " + e, e);
}
}
}
|