diff --git a/jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java b/jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java index eb0861f8f130344a7e44f738c83223815bdcdcf3..aa4a64df75bc7c6c0de3d019f46b23e3e08993b3 100644 --- a/jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java +++ b/jadx-core/src/main/java/jadx/core/deobf/Deobfuscator.java @@ -3,7 +3,7 @@ package jadx.core.deobf; import java.io.File; import java.util.ArrayList; import java.util.HashMap; -import java.util.HashSet; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -142,87 +142,72 @@ public class Deobfuscator { ovrdMap.clear(); } - @Nullable - private static ClassNode resolveOverridingInternal(DexNode dex, ClassNode cls, String signature, - Set overrideSet, ClassNode rootClass) { - ClassNode result = null; - - for (MethodNode m : cls.getMethods()) { - if (m.getMethodInfo().getShortId().startsWith(signature)) { - result = cls; - overrideSet.add(m.getMethodInfo()); - break; + private void resolveOverriding(MethodNode mth) { + Set clsParents = new LinkedHashSet<>(); + collectClassHierarchy(mth.getParentClass(), clsParents); + + String mthSignature = mth.getMethodInfo().makeSignature(false); + Set overrideSet = new LinkedHashSet<>(); + for (ClassNode classNode : clsParents) { + MethodInfo methodInfo = getMthOverride(classNode.getMethods(), mthSignature); + if (methodInfo != null) { + overrideSet.add(methodInfo); + } + } + if (overrideSet.isEmpty()) { + return; + } + OverridedMethodsNode overrideNode = getOverrideMethodsNode(overrideSet); + if (overrideNode == null) { + overrideNode = new OverridedMethodsNode(overrideSet); + ovrd.add(overrideNode); + } + for (MethodInfo overrideMth : overrideSet) { + if (!ovrdMap.containsKey(overrideMth)) { + ovrdMap.put(overrideMth, overrideNode); + overrideNode.add(overrideMth); } } + } - ArgType superClass = cls.getSuperClass(); - if (superClass != null) { - ClassNode superNode = dex.resolveClass(superClass); - if (superNode != null) { - ClassNode clsWithMth = resolveOverridingInternal(dex, superNode, signature, overrideSet, rootClass); - if (clsWithMth != null) { - if ((result != null) && (result != cls)) { - if (clsWithMth != result) { - LOG.warn(String.format("Multiple overriding '%s' from '%s' and '%s' in '%s'", - signature, - result.getFullName(), clsWithMth.getFullName(), - rootClass.getFullName())); - } - } else { - result = clsWithMth; - } - } + private OverridedMethodsNode getOverrideMethodsNode(Set overrideSet) { + for (MethodInfo overrideMth : overrideSet) { + OverridedMethodsNode node = ovrdMap.get(overrideMth); + if (node != null) { + return node; } } + return null; + } - for (ArgType iFaceType : cls.getInterfaces()) { - ClassNode iFaceNode = dex.resolveClass(iFaceType); - if (iFaceNode != null) { - ClassNode clsWithMth = resolveOverridingInternal(dex, iFaceNode, signature, overrideSet, rootClass); - if (clsWithMth != null) { - if ((result != null) && (result != cls)) { - if (clsWithMth != result) { - LOG.warn(String.format("Multiple overriding '%s' from '%s' and '%s' in '%s'", - signature, - result.getFullName(), clsWithMth.getFullName(), - rootClass.getFullName())); - } - } else { - result = clsWithMth; - } - } + private MethodInfo getMthOverride(List methods, String mthSignature) { + for (MethodNode m : methods) { + MethodInfo mthInfo = m.getMethodInfo(); + if (mthInfo.getShortId().startsWith(mthSignature)) { + return mthInfo; } } - return result; + return null; } - private void resolveOverriding(MethodNode mth) { - Set overrideSet = new HashSet<>(); - String mthSignature = mth.getMethodInfo().makeSignature(false); - ClassNode cls = mth.getParentClass(); - resolveOverridingInternal(mth.dex(), cls, mthSignature, overrideSet, cls); - if (overrideSet.size() > 1) { - OverridedMethodsNode overrideNode = null; - for (MethodInfo _mth : overrideSet) { - if (ovrdMap.containsKey(_mth)) { - overrideNode = ovrdMap.get(_mth); - break; + private void collectClassHierarchy(ClassNode cls, Set collected) { + boolean added = collected.add(cls); + if (added) { + ArgType superClass = cls.getSuperClass(); + if (superClass != null) { + ClassNode superNode = cls.dex().resolveClass(superClass); + if (superNode != null) { + collectClassHierarchy(superNode, collected); } } - if (overrideNode == null) { - overrideNode = new OverridedMethodsNode(overrideSet); - ovrd.add(overrideNode); - } - for (MethodInfo _mth : overrideSet) { - if (!ovrdMap.containsKey(_mth)) { - ovrdMap.put(_mth, overrideNode); - if (!overrideNode.contains(_mth)) { - overrideNode.add(_mth); - } + + for (ArgType argType : cls.getInterfaces()) { + ClassNode interfaceNode = cls.dex().resolveClass(argType); + if (interfaceNode != null) { + collectClassHierarchy(interfaceNode, collected); } } } - overrideSet.clear(); } private void processClass(ClassNode cls) { diff --git a/jadx-core/src/main/java/jadx/core/deobf/OverridedMethodsNode.java b/jadx-core/src/main/java/jadx/core/deobf/OverridedMethodsNode.java index d9fe687e652b72f0c94917921a68ffd9ad2be2be..7c4c0e8555adf7046cdeac0487b4c8001a7a90f4 100644 --- a/jadx-core/src/main/java/jadx/core/deobf/OverridedMethodsNode.java +++ b/jadx-core/src/main/java/jadx/core/deobf/OverridedMethodsNode.java @@ -4,7 +4,7 @@ import java.util.Set; import jadx.core.dex.info.MethodInfo; -/* package */ class OverridedMethodsNode { +class OverridedMethodsNode { private Set methods; diff --git a/jadx-core/src/test/java/jadx/tests/integration/deobf/TestMthRename.java b/jadx-core/src/test/java/jadx/tests/integration/deobf/TestMthRename.java index 0045021659c284bde09355587b5498912dce1c09..6bb21a2886217c2763e6621e8859a574af6e7bdc 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/deobf/TestMthRename.java +++ b/jadx-core/src/test/java/jadx/tests/integration/deobf/TestMthRename.java @@ -30,10 +30,10 @@ public class TestMthRename extends IntegrationTest { ClassNode cls = getClassNode(TestCls.class); String code = cls.getCode().toString(); - assertThat(code, containsString("public abstract void m0a();")); + assertThat(code, containsString("public abstract void mo1a();")); assertThat(code, not(containsString("public abstract void a();"))); - assertThat(code, containsString(".m0a();")); + assertThat(code, containsString(".mo1a();")); assertThat(code, not(containsString(".a();"))); } }