Commit 68ccf57b authored by Skylot's avatar Skylot

core: fix type detection for method arguments

parent 84970759
...@@ -680,7 +680,7 @@ public class InsnGen { ...@@ -680,7 +680,7 @@ public class InsnGen {
if (!arg.getType().equals(origType)) { if (!arg.getType().equals(origType)) {
code.add('('); code.add('(');
useType(code, origType); useType(code, origType);
code.add(')'); code.add(") ");
addArg(code, arg, true); addArg(code, arg, true);
} else { } else {
addArg(code, arg, false); addArg(code, arg, false);
......
...@@ -39,6 +39,7 @@ public class MthParameterArg extends RegisterArg { ...@@ -39,6 +39,7 @@ public class MthParameterArg extends RegisterArg {
if (isThis) { if (isThis) {
sVar.setName("this"); sVar.setName("this");
} }
sVar.setTypeImmutable(type);
super.setSVar(sVar); super.setSVar(sVar);
} }
......
...@@ -80,6 +80,7 @@ public class RegisterArg extends InsnArg implements Named { ...@@ -80,6 +80,7 @@ public class RegisterArg extends InsnArg implements Named {
setName(name); setName(name);
} }
@Deprecated
public void forceType(ArgType type) { public void forceType(ArgType type) {
this.type = type; this.type = type;
} }
......
...@@ -19,6 +19,7 @@ public class SSAVar { ...@@ -19,6 +19,7 @@ public class SSAVar {
private PhiInsn usedInPhi; private PhiInsn usedInPhi;
private ArgType type; private ArgType type;
private boolean typeImmutable;
public SSAVar(int regNum, int v, RegisterArg assign) { public SSAVar(int regNum, int v, RegisterArg assign) {
this.regNum = regNum; this.regNum = regNum;
...@@ -33,10 +34,6 @@ public class SSAVar { ...@@ -33,10 +34,6 @@ public class SSAVar {
endUseAddr = -1; endUseAddr = -1;
} }
public int getRegNum() {
return regNum;
}
public int getStartAddr() { public int getStartAddr() {
if (startUseAddr == -1) { if (startUseAddr == -1) {
calcUsageAddrRange(); calcUsageAddrRange();
...@@ -48,7 +45,6 @@ public class SSAVar { ...@@ -48,7 +45,6 @@ public class SSAVar {
if (endUseAddr == -1) { if (endUseAddr == -1) {
calcUsageAddrRange(); calcUsageAddrRange();
} }
return endUseAddr; return endUseAddr;
} }
...@@ -78,12 +74,16 @@ public class SSAVar { ...@@ -78,12 +74,16 @@ public class SSAVar {
} }
} }
if ((start != Integer.MAX_VALUE) if ((start != Integer.MAX_VALUE)
&& (end != Integer.MIN_VALUE)) { && (end != Integer.MIN_VALUE)) {
startUseAddr = start; startUseAddr = start;
endUseAddr = end; endUseAddr = end;
} }
} }
public int getRegNum() {
return regNum;
}
public int getVersion() { public int getVersion() {
return version; return version;
...@@ -141,20 +141,32 @@ public class SSAVar { ...@@ -141,20 +141,32 @@ public class SSAVar {
return useList.size() + usedInPhi.getResult().getSVar().getUseCount(); return useList.size() + usedInPhi.getResult().getSVar().getUseCount();
} }
public ArgType getType() {
return type;
}
public void setType(ArgType type) { public void setType(ArgType type) {
this.type = type; ArgType acceptedType;
if (typeImmutable) {
// don't change type, just update types in useList
acceptedType = this.type;
} else {
acceptedType = type;
this.type = acceptedType;
}
if (assign != null) { if (assign != null) {
assign.type = type; assign.type = acceptedType;
} }
for (int i = 0, useListSize = useList.size(); i < useListSize; i++) { for (int i = 0, useListSize = useList.size(); i < useListSize; i++) {
useList.get(i).type = type; useList.get(i).type = acceptedType;
} }
} }
public void setTypeImmutable(ArgType type) {
setType(type);
this.typeImmutable = true;
}
public boolean isTypeImmutable() {
return typeImmutable;
}
public void setName(String name) { public void setName(String name) {
if (name != null) { if (name != null) {
if (varName == null) { if (varName == null) {
......
...@@ -85,20 +85,21 @@ public class PostTypeInference { ...@@ -85,20 +85,21 @@ public class PostTypeInference {
case CHECK_CAST: { case CHECK_CAST: {
ArgType castType = (ArgType) ((IndexInsnNode) insn).getIndex(); ArgType castType = (ArgType) ((IndexInsnNode) insn).getIndex();
SSAVar sVar = insn.getResult().getSVar(); RegisterArg result = insn.getResult();
// don't override generic types of same base class // don't override generic types of same base class
boolean skip = castType.isObject() && castType.getObject().equals(sVar.getType().getObject()); boolean skip = castType.isObject() && castType.getObject().equals(result.getType().getObject());
if (!skip) { if (!skip) {
// workaround for compiler bug (see TestDuplicateCast) // workaround for compiler bug (see TestDuplicateCast)
sVar.setType(castType); result.getSVar().setType(castType);
} }
return true; return true;
} }
case PHI: { case PHI: {
PhiInsn phi = (PhiInsn) insn; PhiInsn phi = (PhiInsn) insn;
SSAVar resultSVar = phi.getResult().getSVar(); RegisterArg result = phi.getResult();
if (resultSVar != null && !resultSVar.getType().isTypeKnown()) { SSAVar resultSVar = result.getSVar();
if (resultSVar != null && !result.getType().isTypeKnown()) {
for (InsnArg arg : phi.getArguments()) { for (InsnArg arg : phi.getArguments()) {
ArgType argType = arg.getType(); ArgType argType = arg.getType();
if (argType.isTypeKnown()) { if (argType.isTypeKnown()) {
......
...@@ -44,8 +44,7 @@ public class TypeInference extends AbstractVisitor { ...@@ -44,8 +44,7 @@ public class TypeInference extends AbstractVisitor {
private static ArgType processType(SSAVar var) { private static ArgType processType(SSAVar var) {
RegisterArg assign = var.getAssign(); RegisterArg assign = var.getAssign();
List<RegisterArg> useList = var.getUseList(); List<RegisterArg> useList = var.getUseList();
if (assign != null if (assign != null && (useList.isEmpty() || var.isTypeImmutable())) {
&& (useList.isEmpty() || assign.isTypeImmutable())) {
return assign.getType(); return assign.getType();
} }
ArgType type; ArgType type;
......
package jadx.tests.integration.invoke;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.IntegrationTest;
import org.junit.Test;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
public class TestOverloadedMethodInvoke extends IntegrationTest {
public static class TestCls {
int c;
public void method(Throwable th) {
c++;
if (th != null) {
c+=100;
}
}
public void method(Exception e) {
c += 1000;
if (e != null) {
c += 10000;
}
}
public void test(Throwable th, Exception e) {
method(e);
method(th);
method((Throwable) e);
method((Exception) th);
}
public void check() {
test(null, new Exception());
assertEquals(12102, c);
}
}
@Test
public void test() {
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsString("public void test(Throwable th, Exception e) {"));
assertThat(code, containsOne("method(e);"));
assertThat(code, containsOne("method(th);"));
assertThat(code, containsOne("method((Throwable) e);"));
assertThat(code, containsOne("method((Exception) th);"));
assertThat(code, not(containsString("(Exception) e")));
}
}
package jadx.tests.integration.types;
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 TestTypeResolver2 extends IntegrationTest {
public static class TestCls {
private static boolean test(Object obj) throws IOException {
if (obj != null) {
return true;
}
throw new IOException();
}
}
@Test
public void test() {
noDebugInfo();
ClassNode cls = getClassNode(TestCls.class);
String code = cls.getCode().toString();
assertThat(code, containsOne("if (obj != null) {"));
}
}
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