fix: handle classes 'super' loop (#1942)
This commit is contained in:
@@ -199,6 +199,7 @@ public final class JadxDecompiler implements Closeable {
|
||||
}
|
||||
|
||||
private void loadFinished() {
|
||||
LOG.debug("Load finished");
|
||||
List<JadxPass> list = customPasses.get(JadxAfterLoadPass.TYPE);
|
||||
if (list != null) {
|
||||
for (JadxPass pass : list) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package jadx.core.dex.visitors;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
@@ -281,7 +282,7 @@ public class OverrideMethodVisitor extends AbstractVisitor {
|
||||
|
||||
@Nullable
|
||||
private SuperTypesData collectSuperTypes(ClassNode cls) {
|
||||
List<ArgType> superTypes = new ArrayList<>();
|
||||
Set<ArgType> superTypes = new LinkedHashSet<>();
|
||||
Set<String> endTypes = new HashSet<>();
|
||||
collectSuperTypes(cls, superTypes, endTypes);
|
||||
if (superTypes.isEmpty()) {
|
||||
@@ -290,10 +291,10 @@ public class OverrideMethodVisitor extends AbstractVisitor {
|
||||
if (endTypes.isEmpty()) {
|
||||
throw new JadxRuntimeException("No end types in class hierarchy: " + cls);
|
||||
}
|
||||
return new SuperTypesData(superTypes, endTypes);
|
||||
return new SuperTypesData(new ArrayList<>(superTypes), endTypes);
|
||||
}
|
||||
|
||||
private void collectSuperTypes(ClassNode cls, List<ArgType> superTypes, Set<String> endTypes) {
|
||||
private void collectSuperTypes(ClassNode cls, Set<ArgType> superTypes, Set<String> endTypes) {
|
||||
RootNode root = cls.root();
|
||||
int k = 0;
|
||||
ArgType superClass = cls.getSuperClass();
|
||||
@@ -308,21 +309,24 @@ public class OverrideMethodVisitor extends AbstractVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private int addSuperType(RootNode root, List<ArgType> superTypesMap, Set<String> endTypes, ArgType superType) {
|
||||
private int addSuperType(RootNode root, Set<ArgType> superTypes, Set<String> endTypes, ArgType superType) {
|
||||
if (Objects.equals(superType, ArgType.OBJECT)) {
|
||||
return 0;
|
||||
}
|
||||
superTypesMap.add(superType);
|
||||
if (!superTypes.add(superType)) {
|
||||
// found 'super' loop, stop processing
|
||||
return 0;
|
||||
}
|
||||
ClassNode classNode = root.resolveClass(superType);
|
||||
if (classNode != null) {
|
||||
collectSuperTypes(classNode, superTypesMap, endTypes);
|
||||
collectSuperTypes(classNode, superTypes, endTypes);
|
||||
return 1;
|
||||
}
|
||||
ClspClass clsDetails = root.getClsp().getClsDetails(superType);
|
||||
if (clsDetails != null) {
|
||||
int k = 0;
|
||||
for (ArgType parentType : clsDetails.getParents()) {
|
||||
k += addSuperType(root, superTypesMap, endTypes, parentType);
|
||||
k += addSuperType(root, superTypes, endTypes, parentType);
|
||||
}
|
||||
if (k == 0) {
|
||||
endTypes.add(superType.getObject());
|
||||
|
||||
@@ -3,8 +3,10 @@ package jadx.core.dex.visitors;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
@@ -107,8 +109,14 @@ public class ShadowFieldVisitor extends AbstractVisitor {
|
||||
|
||||
private static List<FieldNode> collectAllInstanceFields(ClassNode cls) {
|
||||
List<FieldNode> fieldsList = new ArrayList<>();
|
||||
Set<ClassNode> visited = new HashSet<>();
|
||||
ClassNode currentClass = cls;
|
||||
while (currentClass != null) {
|
||||
if (!visited.add(currentClass)) {
|
||||
String msg = "Found 'super' loop in classes: " + visited;
|
||||
visited.forEach(c -> c.addWarnComment(msg));
|
||||
return fieldsList;
|
||||
}
|
||||
for (FieldNode field : currentClass.getFields()) {
|
||||
if (!field.getAccessFlags().isStatic()) {
|
||||
fieldsList.add(field);
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package jadx.tests.integration.others;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.SmaliTest;
|
||||
|
||||
import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;
|
||||
|
||||
@SuppressWarnings("CommentedOutCode")
|
||||
public class TestSuperLoop extends SmaliTest {
|
||||
// @formatter:off
|
||||
/*
|
||||
public class A extends B {
|
||||
public int a;
|
||||
}
|
||||
|
||||
public class B extends A {
|
||||
public int b;
|
||||
}
|
||||
*/
|
||||
// @formatter:on
|
||||
|
||||
@Test
|
||||
public void test() {
|
||||
allowWarnInCode();
|
||||
disableCompilation();
|
||||
|
||||
List<ClassNode> clsList = loadFromSmaliFiles();
|
||||
assertThat(searchCls(clsList, "A"))
|
||||
.code()
|
||||
.containsOne("public class A extends B {");
|
||||
|
||||
assertThat(searchCls(clsList, "B"))
|
||||
.code()
|
||||
.containsOne("public class B extends A {");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
.class public LA;
|
||||
.super LB;
|
||||
|
||||
.field public a:I
|
||||
@@ -0,0 +1,4 @@
|
||||
.class public LB;
|
||||
.super LA;
|
||||
|
||||
.field public b:I
|
||||
Reference in New Issue
Block a user