fix: don't rename bridged overridden methods (#1672)
This commit is contained in:
@@ -14,6 +14,9 @@ import jadx.core.Consts;
|
||||
import jadx.core.codegen.json.JsonMappingGen;
|
||||
import jadx.core.deobf.Deobfuscator;
|
||||
import jadx.core.deobf.NameMapper;
|
||||
import jadx.core.dex.attributes.AFlag;
|
||||
import jadx.core.dex.attributes.AType;
|
||||
import jadx.core.dex.attributes.nodes.MethodOverrideAttr;
|
||||
import jadx.core.dex.attributes.nodes.RenameReasonAttr;
|
||||
import jadx.core.dex.info.ClassInfo;
|
||||
import jadx.core.dex.info.FieldInfo;
|
||||
@@ -195,7 +198,7 @@ public class RenameVisitor extends AbstractVisitor {
|
||||
Set<String> names = new HashSet<>(methods.size());
|
||||
for (MethodNode mth : methods) {
|
||||
String signature = mth.getMethodInfo().makeSignature(true, false);
|
||||
if (!names.add(signature)) {
|
||||
if (!names.add(signature) && canRename(mth)) {
|
||||
deobfuscator.forceRenameMethod(mth);
|
||||
mth.addAttr(new RenameReasonAttr("collision with other method in class"));
|
||||
}
|
||||
@@ -203,6 +206,23 @@ public class RenameVisitor extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean canRename(MethodNode mth) {
|
||||
if (mth.contains(AFlag.DONT_RENAME)) {
|
||||
return false;
|
||||
}
|
||||
MethodOverrideAttr overrideAttr = mth.get(AType.METHOD_OVERRIDE);
|
||||
if (overrideAttr != null) {
|
||||
for (MethodNode relatedMth : overrideAttr.getRelatedMthNodes()) {
|
||||
if (relatedMth != mth && mth.getParentClass().equals(relatedMth.getParentClass())) {
|
||||
// ignore rename if exists related method from same class (bridge method in most cases)
|
||||
// such rename will also rename current method and will not help to resolve name collision
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static void processRootPackages(Deobfuscator deobfuscator, RootNode root, List<ClassNode> classes) {
|
||||
Set<String> rootPkgs = collectRootPkgs(classes);
|
||||
root.getCacheStorage().setRootPkgs(rootPkgs);
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
package jadx.tests.integration.inline;
|
||||
|
||||
import org.assertj.core.api.Condition;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.IntegrationTest;
|
||||
import jadx.tests.api.extensions.profiles.TestProfile;
|
||||
import jadx.tests.api.extensions.profiles.TestWithProfiles;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
public class TestSyntheticBridgeRename extends IntegrationTest {
|
||||
|
||||
@SuppressWarnings("InnerClassMayBeStatic")
|
||||
public static class TestCls {
|
||||
private abstract class Inner<V> {
|
||||
public abstract V get(String value);
|
||||
}
|
||||
|
||||
public class IntInner extends Inner<Integer> {
|
||||
public Integer get(String value) {
|
||||
return value.length();
|
||||
}
|
||||
}
|
||||
|
||||
public void test() {
|
||||
IntInner inner = new IntInner();
|
||||
call(inner.get("a"));
|
||||
}
|
||||
|
||||
private static void call(Integer value) {
|
||||
}
|
||||
}
|
||||
|
||||
@TestWithProfiles({ TestProfile.DX_J8, TestProfile.JAVA8 })
|
||||
public void test() {
|
||||
ClassNode cls = getClassNode(TestCls.class);
|
||||
assertThat(searchCls(cls.getInnerClasses(), "IntInner").getMethods())
|
||||
.as("check that bridge method was generated by compiler")
|
||||
.haveAtLeastOne(new Condition<>(mth -> mth.getAccessFlags().isBridge(), "bridge"));
|
||||
|
||||
assertThat(cls)
|
||||
.code()
|
||||
.doesNotContain("mo0get")
|
||||
.containsOne("call(inner.get(\"a\"));");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user