Commit da41efa3 authored by Skylot's avatar Skylot

fix: force rename by checks from RenameVisitor (#432)

parent 9e0cd2e1
......@@ -243,6 +243,10 @@ public class Deobfuscator {
}
}
public void forceRenameField(FieldNode field) {
field.getFieldInfo().setAlias(makeFieldAlias(field));
}
public void renameMethod(MethodNode mth) {
String alias = getMethodAlias(mth);
if (alias != null) {
......@@ -253,6 +257,13 @@ public class Deobfuscator {
}
}
public void forceRenameMethod(MethodNode mth) {
mth.getMethodInfo().setAlias(makeMethodAlias(mth));
if (mth.isVirtual()) {
resolveOverriding(mth);
}
}
public void addPackagePreset(String origPkgName, String pkgAlias) {
PackageNode pkg = getPackageNode(origPkgName, true);
pkg.setAlias(pkgAlias);
......
......@@ -65,6 +65,10 @@ public final class FieldInfo {
return !name.equals(alias);
}
public boolean equalsNameAndType(FieldInfo other) {
return name.equals(other.name) && type.equals(other.type);
}
@Override
public boolean equals(Object o) {
if (this == o) {
......
......@@ -321,6 +321,15 @@ public class ClassNode extends LineAttrNode implements ILoadable, IDexNode {
return null;
}
public FieldNode searchFieldByNameAndType(FieldInfo field) {
for (FieldNode f : fields) {
if (f.getFieldInfo().equalsNameAndType(field)) {
return f;
}
}
return null;
}
public FieldNode searchFieldByName(String name) {
for (FieldNode f : fields) {
if (f.getName().equals(name)) {
......
......@@ -150,16 +150,15 @@ public class DexNode implements IDexNode {
@Nullable
FieldNode deepResolveField(@NotNull ClassNode cls, FieldInfo fieldInfo) {
FieldNode field = cls.searchFieldByName(fieldInfo.getName());
FieldNode field = cls.searchFieldByNameAndType(fieldInfo);
if (field != null) {
return field;
}
FieldNode found;
ArgType superClass = cls.getSuperClass();
if (superClass != null) {
ClassNode superNode = resolveClass(superClass);
if (superNode != null) {
found = deepResolveField(superNode, fieldInfo);
FieldNode found = deepResolveField(superNode, fieldInfo);
if (found != null) {
return found;
}
......@@ -168,7 +167,7 @@ public class DexNode implements IDexNode {
for (ArgType iFaceType : cls.getInterfaces()) {
ClassNode iFaceNode = resolveClass(iFaceType);
if (iFaceNode != null) {
found = deepResolveField(iFaceNode, fieldInfo);
FieldNode found = deepResolveField(iFaceNode, fieldInfo);
if (found != null) {
return found;
}
......
......@@ -12,6 +12,7 @@ import jadx.core.Consts;
import jadx.core.deobf.Deobfuscator;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.info.AccessInfo;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.nodes.ClassNode;
......@@ -19,7 +20,6 @@ import jadx.core.dex.nodes.DexNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.utils.files.FileUtils;
import jadx.core.utils.files.InputFile;
......@@ -49,20 +49,12 @@ public class RenameVisitor extends AbstractVisitor {
checkClasses(root, isCaseSensitive);
}
@Override
public boolean visit(ClassNode cls) throws JadxException {
checkFields(cls);
checkMethods(cls);
for (ClassNode inner : cls.getInnerClasses()) {
visit(inner);
}
return false;
}
private void checkClasses(RootNode root, boolean caseSensitive) {
Set<String> clsNames = new HashSet<>();
for (ClassNode cls : root.getClasses(true)) {
checkClassName(cls);
checkFields(cls);
checkMethods(cls);
if (!caseSensitive) {
ClassInfo classInfo = cls.getClassInfo();
String clsFileName = classInfo.getAlias().getFullPath();
......@@ -103,7 +95,7 @@ public class RenameVisitor extends AbstractVisitor {
FieldInfo fieldInfo = field.getFieldInfo();
String fieldName = fieldInfo.getAlias();
if (!names.add(fieldName) || !NameMapper.isValidIdentifier(fieldName)) {
deobfuscator.renameField(field);
deobfuscator.forceRenameField(field);
}
}
}
......@@ -111,12 +103,16 @@ public class RenameVisitor extends AbstractVisitor {
private void checkMethods(ClassNode cls) {
Set<String> names = new HashSet<>();
for (MethodNode mth : cls.getMethods()) {
if (mth.contains(AFlag.DONT_GENERATE) || mth.getAccessFlags().isConstructor()) {
AccessInfo accessFlags = mth.getAccessFlags();
if (accessFlags.isConstructor()
|| accessFlags.isBridge()
|| accessFlags.isSynthetic()
|| mth.contains(AFlag.DONT_GENERATE)) {
continue;
}
String signature = mth.getMethodInfo().makeSignature(false);
if (!names.add(signature) || !NameMapper.isValidIdentifier(mth.getAlias())) {
deobfuscator.renameMethod(mth);
deobfuscator.forceRenameMethod(mth);
}
}
}
......
package jadx.tests.integration.names;
import org.junit.Test;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.junit.Assert.assertThat;
public class TestDuplicatedNames extends SmaliTest {
/*
public static class TestCls {
public Object fieldName;
public String fieldName;
public Object run() {
return this.fieldName;
}
public String run() {
return this.fieldName;
}
}
*/
@Test
public void test() {
commonChecks();
}
@Test
public void testWithDeobf() {
enableDeobfuscation();
commonChecks();
}
private void commonChecks() {
ClassNode cls = getClassNodeFromSmaliWithPath("names", "TestDuplicatedNames");
String code = cls.getCode().toString();
assertThat(code, containsOne("Object fieldName;"));
assertThat(code, containsOne("String f0fieldName"));
assertThat(code, containsOne("this.fieldName"));
assertThat(code, containsOne("this.f0fieldName"));
assertThat(code, containsOne("public Object run() {"));
assertThat(code, containsOne("public String m0run() {"));
}
}
.class public LTestDuplicatedNames;
.super Ljava/lang/Object;
.source "TestDuplicatedNames.java"
# instance fields
.field public fieldName:Ljava/lang/String;
.field public fieldName:Ljava/lang/Object;
# direct methods
.method public constructor <init>()V
.registers 1
.prologue
.line 3
invoke-direct {p0}, Ljava/lang/Object;-><init>()V
return-void
.end method
# virtual methods
.method public run()Ljava/lang/String;
.registers 2
.prologue
iget-object v0, p0, LTestDuplicatedNames;->fieldName:Ljava/lang/String;
return-object v0
.end method
.method public run()Ljava/lang/Object;
.registers 2
.prologue
iget-object v0, p0, LTestDuplicatedNames;->fieldName:Ljava/lang/Object;
return-object v0
.end method
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment