Skip to content

Commit

Permalink
core: fix incorrect package for R class (skylot#99)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Mar 19, 2016
1 parent 2b1f815 commit 4e98272
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 28 deletions.
4 changes: 4 additions & 0 deletions jadx-core/src/main/java/jadx/core/codegen/ClassGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -501,6 +501,10 @@ private String useClassInternal(ClassInfo useCls, ClassInfo extClsInfo) {
if (searchCollision(cls.dex(), useCls, extClsInfo)) {
return fullName;
}
// ignore classes from default package
if (extClsInfo.isDefaultPackage()) {
return shortName;
}
if (extClsInfo.getPackage().equals(useCls.getPackage())) {
fullName = extClsInfo.getNameWithoutPackage();
}
Expand Down
9 changes: 3 additions & 6 deletions jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static jadx.core.utils.android.AndroidResourcesUtils.handleAppResField;

public class InsnGen {
private static final Logger LOG = LoggerFactory.getLogger(InsnGen.class);

Expand Down Expand Up @@ -169,12 +171,7 @@ public static void makeStaticFieldAccess(CodeWriter code, FieldInfo field, Class
boolean fieldFromThisClass = clsGen.getClassNode().getClassInfo().equals(declClass);
if (!fieldFromThisClass) {
// Android specific resources class handler
ClassInfo parentClass = declClass.getParentClass();
if (parentClass != null && parentClass.getShortName().equals("R")) {
clsGen.useClass(code, parentClass);
code.add('.');
code.add(declClass.getAlias().getShortName());
} else {
if (!handleAppResField(code, clsGen, declClass)) {
clsGen.useClass(code, declClass);
}
code.add('.');
Expand Down
4 changes: 4 additions & 0 deletions jadx-core/src/main/java/jadx/core/dex/info/ClassInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ public String getPackage() {
return pkg;
}

public boolean isDefaultPackage() {
return pkg.isEmpty();
}

public String getRawName() {
return type.getObject();
}
Expand Down
6 changes: 2 additions & 4 deletions jadx-core/src/main/java/jadx/core/dex/nodes/FieldNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,8 @@ public class FieldNode extends LineAttrNode {
private ArgType type; // store signature

public FieldNode(ClassNode cls, Field field) {
this.parent = cls;
this.fieldInfo = FieldInfo.fromDex(cls.dex(), field.getFieldIndex());
this.type = fieldInfo.getType();
this.accFlags = new AccessInfo(field.getAccessFlags(), AFType.FIELD);
this(cls, FieldInfo.fromDex(cls.dex(), field.getFieldIndex()),
field.getAccessFlags());
}

public FieldNode(ClassNode cls, FieldInfo fieldInfo, int accessFlags) {
Expand Down
32 changes: 14 additions & 18 deletions jadx-core/src/main/java/jadx/core/dex/nodes/RootNode.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import jadx.core.dex.info.ConstStorage;
import jadx.core.utils.ErrorsCounter;
import jadx.core.utils.StringUtils;
import jadx.core.utils.android.AndroidResourcesUtils;
import jadx.core.utils.exceptions.DecodeException;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.files.DexFile;
Expand Down Expand Up @@ -97,24 +98,7 @@ public ResContainer decode(long size, InputStream is) throws IOException {
}

public void initAppResClass() {
ClassNode resCls;
if (appPackage == null) {
appResClass = makeClass("R");
return;
}
String fullName = appPackage + ".R";
resCls = searchClassByName(fullName);
if (resCls != null) {
appResClass = resCls;
} else {
appResClass = makeClass(fullName);
}
}

private ClassNode makeClass(String clsName) {
DexNode firstDex = dexNodes.get(0);
ClassInfo r = ClassInfo.fromName(firstDex, clsName);
return new ClassNode(firstDex, r);
appResClass = AndroidResourcesUtils.searchAppResClass(this);
}

public void initClassPath() throws DecodeException {
Expand Down Expand Up @@ -169,6 +153,18 @@ public ClassNode searchClassByName(String fullName) {
return null;
}

public List<ClassNode> searchClassByShortName(String shortName) {
List<ClassNode> list = new ArrayList<ClassNode>();
for (DexNode dexNode : dexNodes) {
for (ClassNode cls : dexNode.getClasses()) {
if (cls.getClassInfo().getShortName().equals(shortName)) {
list.add(cls);
}
}
}
return list;
}

public List<DexNode> getDexNodes() {
return dexNodes;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package jadx.core.utils.android;

import jadx.core.codegen.ClassGen;
import jadx.core.codegen.CodeWriter;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.DexNode;
import jadx.core.dex.nodes.RootNode;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* Android resources specific handlers
*/
public class AndroidResourcesUtils {
private static final Logger LOG = LoggerFactory.getLogger(AndroidResourcesUtils.class);

public static ClassNode searchAppResClass(RootNode root) {
String appPackage = root.getAppPackage();
String fullName = appPackage != null ? appPackage + ".R" : "R";
ClassNode resCls = root.searchClassByName(fullName);
if (resCls != null) {
return resCls;
}
List<ClassNode> candidates = root.searchClassByShortName("R");
if (candidates.size() == 1) {
return candidates.get(0);
}
if (!candidates.isEmpty()) {
LOG.info("Found several 'R' class candidates: {}", candidates);
}
LOG.warn("Unknown 'R' class, create references to '{}'", fullName);
return makeClass(root, fullName);
}

public static boolean handleAppResField(CodeWriter code, ClassGen clsGen, ClassInfo declClass) {
ClassInfo parentClass = declClass.getParentClass();
if (parentClass != null && parentClass.getShortName().equals("R")) {
clsGen.useClass(code, parentClass);
code.add('.');
code.add(declClass.getAlias().getShortName());
return true;
}
return false;
}

private static ClassNode makeClass(RootNode root, String clsName) {
DexNode firstDex = root.getDexNodes().get(0);
ClassInfo r = ClassInfo.fromName(firstDex, clsName);
return new ClassNode(firstDex, r);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import org.junit.Test;

import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;

public class TestRFieldRestore extends IntegrationTest {
Expand All @@ -31,5 +33,6 @@ public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsOne("return R.id.Button;"));
assertThat(code, not(containsString("import R;")));
}
}

0 comments on commit 4e98272

Please sign in to comment.