Skip to content

Commit

Permalink
fix: improve class search for super call (#1512)
Browse files Browse the repository at this point in the history
  • Loading branch information
skylot committed Jun 5, 2022
1 parent 8123120 commit 0b2e2ed
Show file tree
Hide file tree
Showing 4 changed files with 83 additions and 35 deletions.
3 changes: 3 additions & 0 deletions jadx-core/src/main/java/jadx/core/clsp/ClspGraph.java
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,9 @@ private void addSuperTypes(ClspClass cls, Set<String> result) {
if (isNew) {
addSuperTypes(parentCls, result);
}
} else {
// parent type is unknown
result.add(parentType.getObject());
}
}
}
Expand Down
70 changes: 37 additions & 33 deletions jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -807,14 +807,9 @@ private void makeInvoke(InvokeNode insn, ICodeWriter code) throws CodegenExcepti
break;

case SUPER:
ClassInfo superCallCls = getClassForSuperCall(code, callMth);
if (superCallCls != null) {
useClass(code, superCallCls);
code.add('.');
}
// use 'super' instead 'this' in 0 arg
code.add("super").add('.');
k++;
callSuper(code, callMth);
k++; // use 'super' instead 'this' in 0 arg
code.add('.');
break;

case STATIC:
Expand Down Expand Up @@ -965,34 +960,43 @@ private void makeInlinedLambdaMethod(ICodeWriter code, InvokeCustomNode customNo
code.startLine('}');
}

@Nullable
private ClassInfo getClassForSuperCall(ICodeWriter code, MethodInfo callMth) {
ClassNode useCls = mth.getParentClass();
ClassInfo insnCls = useCls.getClassInfo();
ClassInfo declClass = callMth.getDeclClass();
if (insnCls.equals(declClass)) {
return null;
private void callSuper(ICodeWriter code, MethodInfo callMth) {
ClassInfo superCallCls = getClassForSuperCall(callMth);
if (superCallCls == null) {
// unknown class, add comment to keep that info
code.add("super/*").add(callMth.getDeclClass().getFullName()).add("*/");
return;
}
ClassNode topClass = useCls.getTopParentClass();
if (topClass.getClassInfo().equals(declClass)) {
return declClass;
ClassInfo curClass = mth.getParentClass().getClassInfo();
if (superCallCls.equals(curClass)) {
code.add("super");
return;
}
// search call class
ClassNode nextParent = useCls;
do {
ClassInfo nextClsInfo = nextParent.getClassInfo();
if (nextClsInfo.equals(declClass)
|| ArgType.isInstanceOf(mth.root(), nextClsInfo.getType(), declClass.getType())) {
if (nextParent == useCls) {
return null;
}
return nextClsInfo;
}
nextParent = nextParent.getParentClass();
} while (nextParent != null && nextParent != topClass);
// use custom class
useClass(code, superCallCls);
code.add(".super");
}

// search failed, just return parent class
return useCls.getParentClass().getClassInfo();
/**
* Search call class in super types of this
* and all parent classes (needed for inlined synthetic calls)
*/
@Nullable
private ClassInfo getClassForSuperCall(MethodInfo callMth) {
ArgType declClsType = callMth.getDeclClass().getType();
ClassNode parentNode = mth.getParentClass();
while (true) {
ClassInfo parentCls = parentNode.getClassInfo();
if (ArgType.isInstanceOf(root, parentCls.getType(), declClsType)) {
return parentCls;
}
ClassNode nextParent = parentNode.getParentClass();
if (nextParent == parentNode) {
// no parent, class not found
return null;
}
parentNode = nextParent;
}
}

void generateMethodArguments(ICodeWriter code, BaseInvokeNode insn, int startArgNum,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import javax.tools.DiagnosticListener;
import javax.tools.JavaCompiler;
Expand Down Expand Up @@ -82,7 +81,7 @@ private void compile(List<JavaFileObject> jfObjects) {
arguments.addAll(options.getArguments());

DiagnosticListener<? super JavaFileObject> diagnostic =
diagObj -> System.out.println("Compiler diagnostic: " + diagObj.getMessage(Locale.ROOT));
diagObj -> System.out.println("Compiler diagnostic: " + diagObj);
Writer out = new PrintWriter(System.out);
CompilationTask compilerTask = compiler.getTask(out, fileManager, diagnostic, arguments, null, jfObjects);
if (Boolean.FALSE.equals(compilerTask.call())) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package jadx.tests.integration.invoke;

import org.junit.jupiter.api.Test;

import jadx.tests.api.IntegrationTest;

import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat;

public class TestSuperInvokeUnknown extends IntegrationTest {

public static class TestCls {
public static class BaseClass {
public int doSomething() {
return 0;
}
}

public static class NestedClass extends BaseClass {
@Override
public int doSomething() {
return super.doSomething();
}
}
}

@Test
public void test() {
disableCompilation();
noDebugInfo();
assertThat(getClassNode(TestCls.NestedClass.class)) // BaseClass unknown
.code()
.containsOne("return super.doSomething();");
}

@Test
public void testTopCls() {
noDebugInfo();
assertThat(getClassNode(TestCls.class))
.code()
.containsOne("return super.doSomething();");
}
}

0 comments on commit 0b2e2ed

Please sign in to comment.