提交 3815d30f 编写于 作者: S Skylot

fix: force rename fields and methods with reserved names (#364)

上级 778b9bb8
...@@ -9,6 +9,7 @@ out/ ...@@ -9,6 +9,7 @@ out/
*.iml *.iml
*.ipr *.ipr
*.iws *.iws
.attach_pid*
**/.DS_Store **/.DS_Store
......
...@@ -78,7 +78,7 @@ public class MethodGen { ...@@ -78,7 +78,7 @@ public class MethodGen {
ai = ai.remove(AccessFlags.ACC_PUBLIC); ai = ai.remove(AccessFlags.ACC_PUBLIC);
} }
if (mth.getMethodInfo().isRenamed()) { if (mth.getMethodInfo().isRenamed() && !ai.isConstructor()) {
code.startLine("/* renamed from: ").add(mth.getName()).add(" */"); code.startLine("/* renamed from: ").add(mth.getName()).add(" */");
} }
code.startLineWithNum(mth.getSourceLine()); code.startLineWithNum(mth.getSourceLine());
...@@ -87,7 +87,7 @@ public class MethodGen { ...@@ -87,7 +87,7 @@ public class MethodGen {
if (classGen.addGenericMap(code, mth.getGenericMap())) { if (classGen.addGenericMap(code, mth.getGenericMap())) {
code.add(' '); code.add(' ');
} }
if (mth.getAccessFlags().isConstructor()) { if (ai.isConstructor()) {
code.attachDefinition(mth); code.attachDefinition(mth);
code.add(classGen.getClassNode().getShortName()); // constructor code.add(classGen.getClassNode().getShortName()); // constructor
} else { } else {
......
...@@ -129,7 +129,7 @@ public class Deobfuscator { ...@@ -129,7 +129,7 @@ public class Deobfuscator {
for (MethodInfo mth : o.getMethods()) { for (MethodInfo mth : o.getMethods()) {
if (aliasToUse == null) { if (aliasToUse == null) {
if (mth.isRenamed() && !mth.isAliasFromPreset()) { if (mth.isRenamed() && !mth.isAliasFromPreset()) {
mth.setAlias(String.format("mo%d%s", id, makeName(mth.getName()))); mth.setAlias(String.format("mo%d%s", id, prepareNamePart(mth.getName())));
} }
aliasToUse = mth.getAlias(); aliasToUse = mth.getAlias();
} }
...@@ -350,7 +350,7 @@ public class Deobfuscator { ...@@ -350,7 +350,7 @@ public class Deobfuscator {
if (alias == null) { if (alias == null) {
String clsName = classInfo.getShortName(); String clsName = classInfo.getShortName();
alias = String.format("C%04d%s", clsIndex++, makeName(clsName)); alias = String.format("C%04d%s", clsIndex++, prepareNamePart(clsName));
} }
PackageNode pkg = getPackageNode(classInfo.getPackage(), true); PackageNode pkg = getPackageNode(classInfo.getPackage(), true);
clsMap.put(classInfo, new DeobfClsInfo(this, cls, pkg, alias)); clsMap.put(classInfo, new DeobfClsInfo(this, cls, pkg, alias));
...@@ -426,13 +426,13 @@ public class Deobfuscator { ...@@ -426,13 +426,13 @@ public class Deobfuscator {
} }
public String makeFieldAlias(FieldNode field) { public String makeFieldAlias(FieldNode field) {
String alias = String.format("f%d%s", fldIndex++, makeName(field.getName())); String alias = String.format("f%d%s", fldIndex++, prepareNamePart(field.getName()));
fldMap.put(field.getFieldInfo(), alias); fldMap.put(field.getFieldInfo(), alias);
return alias; return alias;
} }
public String makeMethodAlias(MethodNode mth) { public String makeMethodAlias(MethodNode mth) {
String alias = String.format("m%d%s", mthIndex++, makeName(mth.getName())); String alias = String.format("m%d%s", mthIndex++, prepareNamePart(mth.getName()));
mthMap.put(mth.getMethodInfo(), alias); mthMap.put(mth.getMethodInfo(), alias);
return alias; return alias;
} }
...@@ -454,25 +454,21 @@ public class Deobfuscator { ...@@ -454,25 +454,21 @@ public class Deobfuscator {
String pkgName = pkg.getName(); String pkgName = pkg.getName();
if (!pkg.hasAlias() && shouldRename(pkgName)) { if (!pkg.hasAlias() && shouldRename(pkgName)) {
String pkgAlias = String.format("p%03d%s", pkgIndex++, makeName(pkgName)); String pkgAlias = String.format("p%03d%s", pkgIndex++, prepareNamePart(pkgName));
pkg.setAlias(pkgAlias); pkg.setAlias(pkgAlias);
} }
} }
private boolean shouldRename(String s) { private boolean shouldRename(String s) {
return s.length() > maxLength int len = s.length();
|| s.length() < minLength return len < minLength || len > maxLength
|| NameMapper.isReserved(s) || !NameMapper.isValidIdentifier(s);
|| !NameMapper.isAllCharsPrintable(s);
} }
private String makeName(String name) { private String prepareNamePart(String name) {
if (name.length() > maxLength) { if (name.length() > maxLength) {
return "x" + Integer.toHexString(name.hashCode()); return "x" + Integer.toHexString(name.hashCode());
} }
if (NameMapper.isReserved(name)) {
return name;
}
if (!NameMapper.isAllCharsPrintable(name)) { if (!NameMapper.isAllCharsPrintable(name)) {
return removeInvalidChars(name); return removeInvalidChars(name);
} }
......
...@@ -79,12 +79,14 @@ public class NameMapper { ...@@ -79,12 +79,14 @@ public class NameMapper {
public static boolean isValidIdentifier(String str) { public static boolean isValidIdentifier(String str) {
return notEmpty(str) return notEmpty(str)
&& !isReserved(str)
&& VALID_JAVA_IDENTIFIER.matcher(str).matches() && VALID_JAVA_IDENTIFIER.matcher(str).matches()
&& isAllCharsPrintable(str); && isAllCharsPrintable(str);
} }
public static boolean isValidFullIdentifier(String str) { public static boolean isValidFullIdentifier(String str) {
return notEmpty(str) return notEmpty(str)
&& !isReserved(str)
&& VALID_JAVA_FULL_IDENTIFIER.matcher(str).matches() && VALID_JAVA_FULL_IDENTIFIER.matcher(str).matches()
&& isAllCharsPrintable(str); && isAllCharsPrintable(str);
} }
......
...@@ -10,6 +10,7 @@ import org.apache.commons.io.FilenameUtils; ...@@ -10,6 +10,7 @@ import org.apache.commons.io.FilenameUtils;
import jadx.api.JadxArgs; import jadx.api.JadxArgs;
import jadx.core.Consts; import jadx.core.Consts;
import jadx.core.deobf.Deobfuscator; import jadx.core.deobf.Deobfuscator;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.info.ClassInfo; import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.info.FieldInfo; import jadx.core.dex.info.FieldInfo;
...@@ -100,7 +101,8 @@ public class RenameVisitor extends AbstractVisitor { ...@@ -100,7 +101,8 @@ public class RenameVisitor extends AbstractVisitor {
Set<String> names = new HashSet<>(); Set<String> names = new HashSet<>();
for (FieldNode field : cls.getFields()) { for (FieldNode field : cls.getFields()) {
FieldInfo fieldInfo = field.getFieldInfo(); FieldInfo fieldInfo = field.getFieldInfo();
if (!names.add(fieldInfo.getAlias())) { String fieldName = fieldInfo.getAlias();
if (!names.add(fieldName) || !NameMapper.isValidIdentifier(fieldName)) {
deobfuscator.renameField(field); deobfuscator.renameField(field);
} }
} }
...@@ -109,11 +111,11 @@ public class RenameVisitor extends AbstractVisitor { ...@@ -109,11 +111,11 @@ public class RenameVisitor extends AbstractVisitor {
private void checkMethods(ClassNode cls) { private void checkMethods(ClassNode cls) {
Set<String> names = new HashSet<>(); Set<String> names = new HashSet<>();
for (MethodNode mth : cls.getMethods()) { for (MethodNode mth : cls.getMethods()) {
if (mth.contains(AFlag.DONT_GENERATE)) { if (mth.contains(AFlag.DONT_GENERATE) || mth.getAccessFlags().isConstructor()) {
continue; continue;
} }
String signature = mth.getMethodInfo().makeSignature(false); String signature = mth.getMethodInfo().makeSignature(false);
if (!names.add(signature)) { if (!names.add(signature) || !NameMapper.isValidIdentifier(mth.getAlias())) {
deobfuscator.renameMethod(mth); deobfuscator.renameMethod(mth);
} }
} }
......
...@@ -27,6 +27,7 @@ import jadx.core.dex.nodes.MethodNode; ...@@ -27,6 +27,7 @@ import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode; import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.visitors.DepthTraversal; import jadx.core.dex.visitors.DepthTraversal;
import jadx.core.dex.visitors.IDexTreeVisitor; import jadx.core.dex.visitors.IDexTreeVisitor;
import jadx.core.utils.exceptions.JadxException;
import jadx.core.xmlgen.ResourceStorage; import jadx.core.xmlgen.ResourceStorage;
import jadx.core.xmlgen.entry.ResourceEntry; import jadx.core.xmlgen.entry.ResourceEntry;
import jadx.tests.api.compiler.DynamicCompiler; import jadx.tests.api.compiler.DynamicCompiler;
...@@ -137,13 +138,13 @@ public abstract class IntegrationTest extends TestUtils { ...@@ -137,13 +138,13 @@ public abstract class IntegrationTest extends TestUtils {
} }
protected void decompile(JadxDecompiler jadx, ClassNode cls) { protected void decompile(JadxDecompiler jadx, ClassNode cls) {
List<IDexTreeVisitor> passes = Jadx.getPassesList(jadx.getArgs()); List<IDexTreeVisitor> passes = getPassesList(jadx);
ProcessClass.process(cls, passes, new CodeGen()); ProcessClass.process(cls, passes, new CodeGen());
} }
protected void decompileWithoutUnload(JadxDecompiler d, ClassNode cls) { protected void decompileWithoutUnload(JadxDecompiler jadx, ClassNode cls) {
cls.load(); cls.load();
List<IDexTreeVisitor> passes = Jadx.getPassesList(d.getArgs()); List<IDexTreeVisitor> passes = getPassesList(jadx);
for (IDexTreeVisitor visitor : passes) { for (IDexTreeVisitor visitor : passes) {
DepthTraversal.visit(visitor, cls); DepthTraversal.visit(visitor, cls);
} }
...@@ -151,6 +152,20 @@ public abstract class IntegrationTest extends TestUtils { ...@@ -151,6 +152,20 @@ public abstract class IntegrationTest extends TestUtils {
// don't unload class // don't unload class
} }
private List<IDexTreeVisitor> getPassesList(JadxDecompiler jadx) {
RootNode root = JadxInternalAccess.getRoot(jadx);
List<IDexTreeVisitor> passesList = Jadx.getPassesList(jadx.getArgs());
passesList.forEach(pass -> {
try {
pass.init(root);
} catch (JadxException e) {
e.printStackTrace();
fail(e.getMessage());
}
});
return passesList;
}
protected void generateClsCode(ClassNode cls) { protected void generateClsCode(ClassNode cls) {
try { try {
new CodeGen().visit(cls); new CodeGen().visit(cls);
......
package jadx.tests.integration.names;
import org.junit.Test;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.assertThat;
public class TestReservedNames extends SmaliTest {
/*
public static class TestCls {
public String do; // reserved name
public String 0f; // invalid identifier
public String try() {
return this.do;
}
}
*/
@Test
public void test() {
ClassNode cls = getClassNodeFromSmaliWithPath("names", "TestReservedNames");
String code = cls.getCode().toString();
assertThat(code, not(containsString("public String do;")));
}
}
.class public LTestReservedNames;
.super Ljava/lang/Object;
.source "TestReservedNames.java"
# instance fields
.field public do:Ljava/lang/String; # reserved name
.field public 0f:Ljava/lang/String; # invalid identifier
# 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 try()Ljava/lang/String;
.registers 2
.prologue
.line 8
iget-object v0, p0, LTestReservedNames;->do:Ljava/lang/String;
return-object v0
.end method
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册