From ebd1b0e9c14f46cb55534cbd48084666afbdef21 Mon Sep 17 00:00:00 2001 From: Ben Gruver Date: Tue, 25 Dec 2012 18:04:28 -0800 Subject: [PATCH] Ensure class permissions are valid when resolving a field while deodexing --- .../jf/dexlib/Code/Analysis/DeodexUtil.java | 38 +++++++++++-------- .../dexlib/Code/Analysis/MethodAnalyzer.java | 9 ++++- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java index f31ec561..d4cf3a8e 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java @@ -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 parents = new ArrayList(); 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; } } diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java index 64f8ab6e..9edf37b1 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java @@ -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));