Ensure class permissions are valid when resolving a field while deodexing

This commit is contained in:
Ben Gruver 2012-12-25 18:04:28 -08:00
parent 650d426c12
commit ebd1b0e9c1
2 changed files with 31 additions and 16 deletions

View File

@ -64,20 +64,21 @@ public class DeodexUtil {
return inlineMethodResolver.resolveExecuteInline(instruction);
}
public FieldIdItem lookupField(ClassPath.ClassDef classDef, int fieldOffset) {
ClassPath.FieldDef field = classDef.getInstanceField(fieldOffset);
public FieldIdItem lookupField(ClassPath.ClassDef accessingClass, ClassPath.ClassDef instanceClass,
int fieldOffset) {
ClassPath.FieldDef field = instanceClass.getInstanceField(fieldOffset);
if (field == null) {
return null;
}
return parseAndResolveField(classDef, field);
return parseAndResolveField(accessingClass, instanceClass, field);
}
private static final Pattern shortMethodPattern = Pattern.compile("([^(]+)\\(([^)]*)\\)(.+)");
public MethodIdItem lookupVirtualMethod(ClassPath.ClassDef accessingClass, ClassPath.ClassDef definingClass,
public MethodIdItem lookupVirtualMethod(ClassPath.ClassDef accessingClass, ClassPath.ClassDef instanceClass,
int methodIndex) {
String method = definingClass.getVirtualMethod(methodIndex);
String method = instanceClass.getVirtualMethod(methodIndex);
if (method == null) {
return null;
}
@ -92,16 +93,16 @@ public class DeodexUtil {
String methodParams = m.group(2);
String methodRet = m.group(3);
if (definingClass instanceof ClassPath.UnresolvedClassDef) {
if (instanceClass instanceof ClassPath.UnresolvedClassDef) {
//if this is an unresolved class, the only way getVirtualMethod could have found a method is if the virtual
//method being looked up was a method on java.lang.Object.
definingClass = ClassPath.getClassDef("Ljava/lang/Object;");
} else if (definingClass.isInterface()) {
definingClass = definingClass.getSuperclass();
assert definingClass != null;
instanceClass = ClassPath.getClassDef("Ljava/lang/Object;");
} else if (instanceClass.isInterface()) {
instanceClass = instanceClass.getSuperclass();
assert instanceClass != null;
}
return parseAndResolveMethod(accessingClass, definingClass, methodName, methodParams, methodRet);
return parseAndResolveMethod(accessingClass, instanceClass, methodName, methodParams, methodRet);
}
private MethodIdItem parseAndResolveMethod(ClassPath.ClassDef accessingClass, ClassPath.ClassDef definingClass,
@ -203,7 +204,6 @@ public class DeodexUtil {
do {
TypeIdItem classTypeItem = TypeIdItem.lookupTypeIdItem(dexFile, methodClassDef.getClassType());
if (classTypeItem != null) {
MethodIdItem methodIdItem = MethodIdItem.lookupMethodIdItem(dexFile, classTypeItem, protoItem, methodNameItem);
if (methodIdItem != null && checkClassAccess(accessingClass, methodClassDef)) {
@ -229,7 +229,15 @@ public class DeodexUtil {
return classRef.substring(1, lastSlash);
}
private FieldIdItem parseAndResolveField(ClassPath.ClassDef classDef, ClassPath.FieldDef field) {
/**
*
* @param accessingClass The class that contains the field reference. I.e. the class being deodexed
* @param instanceClass The inferred class type of the object that the field is being accessed on
* @param field The field being accessed
* @return The FieldIdItem of the resolved field
*/
private FieldIdItem parseAndResolveField(ClassPath.ClassDef accessingClass, ClassPath.ClassDef instanceClass,
ClassPath.FieldDef field) {
String definingClass = field.definingClass;
String fieldName = field.name;
String fieldType = field.type;
@ -244,7 +252,7 @@ public class DeodexUtil {
return null;
}
ClassPath.ClassDef fieldClass = classDef;
ClassPath.ClassDef fieldClass = instanceClass;
ArrayList<ClassPath.ClassDef> parents = new ArrayList<ClassPath.ClassDef>();
parents.add(fieldClass);
@ -263,7 +271,7 @@ public class DeodexUtil {
}
FieldIdItem fieldIdItem = FieldIdItem.lookupFieldIdItem(dexFile, classTypeItem, fieldTypeItem, fieldNameItem);
if (fieldIdItem != null) {
if (fieldIdItem != null && checkClassAccess(accessingClass, fieldClass)) {
return fieldIdItem;
}
}

View File

@ -3578,7 +3578,14 @@ public class MethodAnalyzer {
return false;
}
FieldIdItem fieldIdItem = deodexUtil.lookupField(objectRegisterType.type, fieldOffset);
ClassPath.ClassDef accessingClass =
ClassPath.getClassDef(this.encodedMethod.method.getContainingClass(), false);
if (accessingClass == null) {
throw new ExceptionWithContext(String.format("Could not find ClassDef for current class: %s",
this.encodedMethod.method.getContainingClass()));
}
FieldIdItem fieldIdItem = deodexUtil.lookupField(accessingClass, objectRegisterType.type, fieldOffset);
if (fieldIdItem == null) {
throw new ValidationException(String.format("Could not resolve the field in class %s at offset %d",
objectRegisterType.type.getClassType(), fieldOffset));