Commit 68ccf57b authored by Skylot's avatar Skylot

core: fix type detection for method arguments

parent 84970759
......@@ -680,7 +680,7 @@ public class InsnGen {
if (!arg.getType().equals(origType)) {
code.add('(');
useType(code, origType);
code.add(')');
code.add(") ");
addArg(code, arg, true);
} else {
addArg(code, arg, false);
......
......@@ -39,6 +39,7 @@ public class MthParameterArg extends RegisterArg {
if (isThis) {
sVar.setName("this");
}
sVar.setTypeImmutable(type);
super.setSVar(sVar);
}
......
......@@ -80,6 +80,7 @@ public class RegisterArg extends InsnArg implements Named {
setName(name);
}
@Deprecated
public void forceType(ArgType type) {
this.type = type;
}
......
......@@ -19,6 +19,7 @@ public class SSAVar {
private PhiInsn usedInPhi;
private ArgType type;
private boolean typeImmutable;
public SSAVar(int regNum, int v, RegisterArg assign) {
this.regNum = regNum;
......@@ -33,10 +34,6 @@ public class SSAVar {
endUseAddr = -1;
}
public int getRegNum() {
return regNum;
}
public int getStartAddr() {
if (startUseAddr == -1) {
calcUsageAddrRange();
......@@ -48,7 +45,6 @@ public class SSAVar {
if (endUseAddr == -1) {
calcUsageAddrRange();
}
return endUseAddr;
}
......@@ -78,12 +74,16 @@ public class SSAVar {
}
}
if ((start != Integer.MAX_VALUE)
if ((start != Integer.MAX_VALUE)
&& (end != Integer.MIN_VALUE)) {
startUseAddr = start;
endUseAddr = end;
}
}
}
public int getRegNum() {
return regNum;
}
public int getVersion() {
return version;
......@@ -141,20 +141,32 @@ public class SSAVar {
return useList.size() + usedInPhi.getResult().getSVar().getUseCount();
}
public ArgType getType() {
return 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) {
assign.type = type;
assign.type = acceptedType;
}
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) {
if (name != null) {
if (varName == null) {
......
......@@ -85,20 +85,21 @@ public class PostTypeInference {
case CHECK_CAST: {
ArgType castType = (ArgType) ((IndexInsnNode) insn).getIndex();
SSAVar sVar = insn.getResult().getSVar();
RegisterArg result = insn.getResult();
// 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) {
// workaround for compiler bug (see TestDuplicateCast)
sVar.setType(castType);
result.getSVar().setType(castType);
}
return true;
}
case PHI: {
PhiInsn phi = (PhiInsn) insn;
SSAVar resultSVar = phi.getResult().getSVar();
if (resultSVar != null && !resultSVar.getType().isTypeKnown()) {
RegisterArg result = phi.getResult();
SSAVar resultSVar = result.getSVar();
if (resultSVar != null && !result.getType().isTypeKnown()) {
for (InsnArg arg : phi.getArguments()) {
ArgType argType = arg.getType();
if (argType.isTypeKnown()) {
......
......@@ -44,8 +44,7 @@ public class TypeInference extends AbstractVisitor {
private static ArgType processType(SSAVar var) {
RegisterArg assign = var.getAssign();
List<RegisterArg> useList = var.getUseList();
if (assign != null
&& (useList.isEmpty() || assign.isTypeImmutable())) {
if (assign != null && (useList.isEmpty() || var.isTypeImmutable())) {
return assign.getType();
}
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