提交 08f9a90c 编写于 作者: S Skylot

fix: force cast for null args in method invoke (temp fix for #724)

上级 9f06d674
......@@ -769,7 +769,7 @@ public class InsnGen {
if (!firstArg) {
code.add(", ");
}
boolean cast = overloaded && processOverloadedArg(code, insn, callMth, arg, i - startArgNum);
boolean cast = addArgCast(code, insn, callMth, arg, i - startArgNum, overloaded);
if (!cast && i == argsCount - 1 && processVarArg(code, callMth, arg)) {
continue;
}
......@@ -781,42 +781,47 @@ public class InsnGen {
}
/**
* Add additional cast for overloaded method argument.
* Add additional cast for method argument.
*/
private boolean processOverloadedArg(CodeWriter code, InsnNode insn, MethodNode callMth, InsnArg arg, int origPos) {
List<ArgType> argTypes = callMth.getArgTypes();
ArgType origType = argTypes.get(origPos);
if (origType.isGenericType() && !callMth.getParentClass().equals(mth.getParentClass())) {
// cancel cast
return false;
}
private boolean addArgCast(CodeWriter code, InsnNode insn, @Nullable MethodNode callMth,
InsnArg arg, int origPos, boolean overloaded) {
ArgType castType = null;
if (insn instanceof CallMthInterface && origType.containsGenericType()) {
ArgType clsType;
CallMthInterface mthCall = (CallMthInterface) insn;
RegisterArg instanceArg = mthCall.getInstanceArg();
if (instanceArg != null) {
clsType = instanceArg.getType();
} else {
clsType = mthCall.getCallMth().getDeclClass().getType();
if (callMth != null) {
List<ArgType> argTypes = callMth.getArgTypes();
ArgType origType = argTypes.get(origPos);
if (origType.isGenericType() && !callMth.getParentClass().equals(mth.getParentClass())) {
// cancel cast
return false;
}
ArgType replacedType = TypeUtils.replaceClassGenerics(root, clsType, origType);
if (replacedType != null) {
castType = replacedType;
if (insn instanceof CallMthInterface && origType.containsGenericType()) {
ArgType clsType;
CallMthInterface mthCall = (CallMthInterface) insn;
RegisterArg instanceArg = mthCall.getInstanceArg();
if (instanceArg != null) {
clsType = instanceArg.getType();
} else {
clsType = mthCall.getCallMth().getDeclClass().getType();
}
ArgType replacedType = TypeUtils.replaceClassGenerics(root, clsType, origType);
if (replacedType != null) {
castType = replacedType;
}
if (castType == null) {
ArgType invReplType = TypeUtils.replaceMethodGenerics(root, insn, origType);
if (invReplType != null) {
castType = invReplType;
}
}
}
if (castType == null) {
ArgType invReplType = TypeUtils.replaceMethodGenerics(root, insn, origType);
if (invReplType != null) {
castType = invReplType;
}
castType = origType;
}
}
if (castType == null) {
castType = origType;
} else {
castType = arg.getType();
}
// TODO: check castType for left type variables
if (isCastNeeded(arg, castType)) {
if (isCastNeeded(arg, castType, overloaded)) {
code.add('(');
useType(code, castType);
code.add(") ");
......@@ -825,7 +830,7 @@ public class InsnGen {
return false;
}
private boolean isCastNeeded(InsnArg arg, ArgType origType) {
private boolean isCastNeeded(InsnArg arg, ArgType origType, boolean overloaded) {
ArgType argType = arg.getType();
if (arg.isLiteral() && ((LiteralArg) arg).getLiteral() == 0
&& (argType.isObject() || argType.isArray())) {
......@@ -834,7 +839,7 @@ public class InsnGen {
if (argType.equals(origType)) {
return false;
}
return true;
return overloaded;
}
/**
......
package jadx.tests.integration.invoke;
import org.junit.jupiter.api.Test;
import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;
import static jadx.tests.api.utils.JadxMatchers.containsOne;
import static org.hamcrest.MatcherAssert.assertThat;
public class TestCastInOverloadedInvoke2 extends SmaliTest {
@Test
public void test() {
disableCompilation();
ClassNode cls = getClassNodeFromSmali();
String code = cls.getCode().toString();
assertThat(code, containsOne("new Intent().putExtra(\"param\", (Parcelable) null);"));
}
}
......@@ -39,11 +39,10 @@ public class TestDeboxing2 extends IntegrationTest {
assertThat(code, containsOne("l = 0L;"));
// checks for 'check' method
assertThat(code, containsOne("test(null)"));
assertThat(code, containsOne("test((Long) null)")); // TODO: cast not needed
assertThat(code, containsOne("test(0L)"));
assertThat(code, countString(2, "is(0L)"));
assertThat(code, containsOne("test(7L)"));
assertThat(code, containsOne("is(7L)"));
}
}
.class public Linvoke/TestCastInOverloadedInvoke2;
.super Ljava/lang/Object;
.method public test()V
.locals 3
new-instance v0, Landroid/content/Intent;
invoke-direct {v0}, Landroid/content/Intent;-><init>()V
const-string v1, "param"
const/4 v2, 0x0
invoke-virtual {v0, v1, v2}, Landroid/content/Intent;->putExtra(Ljava/lang/String;Landroid/os/Parcelable;)Landroid/content/Intent;
return-void
.end method
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册