Ensure class permissions are valid when resolving a field while deodexing
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 f31ec56..d4cf3a8 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
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 64f8ab6..9edf37b 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 @@
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));