Commit 932966b6 authored by Skylot's avatar Skylot

core: skip synthetic arguments in anonymous class constructor

parent 85a18e6d
......@@ -647,6 +647,10 @@ public class InsnGen {
if (arg.contains(AFlag.SKIP_ARG)) {
continue;
}
RegisterArg callArg = getCallMthArg(callMth, i - startArgNum);
if (callArg != null && callArg.contains(AFlag.SKIP_ARG)) {
continue;
}
if (i != k) {
code.add(", ");
}
......@@ -660,6 +664,17 @@ public class InsnGen {
code.add(')');
}
private static RegisterArg getCallMthArg(@Nullable MethodNode callMth, int num) {
if (callMth == null) {
return null;
}
List<RegisterArg> args = callMth.getArguments(false);
if (args != null && num < args.size()) {
return args.get(num);
}
return null;
}
/**
* Add additional cast for overloaded method argument.
*/
......
......@@ -11,6 +11,7 @@ import jadx.core.dex.instructions.IndexInsnNode;
import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.instructions.mods.ConstructorInsn;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.ClassNode;
......@@ -135,13 +136,24 @@ public class ClassModifier extends AbstractVisitor {
mth.add(AFlag.DONT_GENERATE);
continue;
}
// remove synthetic constructor for inner non-static classes
// remove synthetic constructor for inner classes
if (af.isSynthetic() && af.isConstructor() && mth.getBasicBlocks().size() == 2) {
List<InsnNode> insns = mth.getBasicBlocks().get(0).getInstructions();
if (insns.size() == 1 && insns.get(0).getType() == InsnType.CONSTRUCTOR) {
ConstructorInsn constr = (ConstructorInsn) insns.get(0);
if (constr.isThis() && !mth.getArguments(false).isEmpty()) {
mth.removeFirstArgument();
List<RegisterArg> args = mth.getArguments(false);
if (constr.isThis() && !args.isEmpty()) {
// remove first arg for non-static class (references to outer class)
if (args.get(0).getType().equals(cls.getParentClass().getClassInfo().getType())) {
args.get(0).add(AFlag.SKIP_ARG);
}
// remove unused args
for (RegisterArg arg : args) {
SSAVar sVar = arg.getSVar();
if (sVar != null && sVar.getUseCount() == 0) {
arg.add(AFlag.SKIP_ARG);
}
}
mth.add(AFlag.DONT_GENERATE);
}
}
......
package jadx.tests.integration.invoke;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import java.io.IOException;
import org.junit.Test;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.junit.Assert.assertThat;
public class TestInvoke1 extends IntegrationTest {
public static class TestCls {
private A is;
private C test(int start) throws IOException {
int id = is.readInt32();
String name = is.readString16Fixed(128);
long typeStringsOffset = start + is.readInt32();
long keyStringsOffset = start + is.readInt32();
String[] types = null;
if (typeStringsOffset != 0) {
types = strs();
}
String[] keys = null;
if (keyStringsOffset != 0) {
keys = strs();
}
C pkg = new C(id, name, types, keys);
if (id == 0x7F) {
is.readInt32();
}
return pkg;
}
private String[] strs() {
return new String[0];
}
private static final class C {
public C(int id, String name, String[] types, String[] keys) {
}
}
private final class A {
public int readInt32() {
return 0;
}
public String readString16Fixed(int i) {
return null;
}
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsOne("C pkg = new C(id, name, types, keys);"));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment