@@ -46,6 +46,7 @@ public class InvokeNode extends InsnNode implements CallMthInterface {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodInfo getCallMth() {
|
||||
return mth;
|
||||
}
|
||||
|
||||
@@ -81,6 +81,7 @@ public class RegisterArg extends InsnArg implements Named {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
if (isThis()) {
|
||||
return THIS_ARG_NAME;
|
||||
@@ -91,6 +92,7 @@ public class RegisterArg extends InsnArg implements Named {
|
||||
return sVar.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setName(String name) {
|
||||
if (sVar != null && name != null) {
|
||||
sVar.setName(name);
|
||||
|
||||
@@ -1,9 +1,15 @@
|
||||
package jadx.core.dex.visitors.typeinference;
|
||||
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.instructions.args.RegisterArg;
|
||||
|
||||
public interface ITypeBound {
|
||||
BoundEnum getBound();
|
||||
|
||||
ArgType getType();
|
||||
|
||||
@Nullable
|
||||
RegisterArg getArg();
|
||||
}
|
||||
|
||||
@@ -3,14 +3,22 @@ package jadx.core.dex.visitors.typeinference;
|
||||
import java.util.Objects;
|
||||
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.instructions.args.RegisterArg;
|
||||
|
||||
public final class TypeBoundConst implements ITypeBound {
|
||||
private final BoundEnum bound;
|
||||
private final ArgType type;
|
||||
private final RegisterArg arg;
|
||||
|
||||
|
||||
public TypeBoundConst(BoundEnum bound, ArgType type) {
|
||||
this(bound, type, null);
|
||||
}
|
||||
|
||||
public TypeBoundConst(BoundEnum bound, ArgType type, RegisterArg arg) {
|
||||
this.bound = bound;
|
||||
this.type = type;
|
||||
this.arg = arg;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -23,6 +31,11 @@ public final class TypeBoundConst implements ITypeBound {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegisterArg getArg() {
|
||||
return arg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
|
||||
+42
-2
@@ -21,6 +21,7 @@ import jadx.core.dex.instructions.IndexInsnNode;
|
||||
import jadx.core.dex.instructions.InsnType;
|
||||
import jadx.core.dex.instructions.PhiInsn;
|
||||
import jadx.core.dex.instructions.args.ArgType;
|
||||
import jadx.core.dex.instructions.args.CodeVar;
|
||||
import jadx.core.dex.instructions.args.InsnArg;
|
||||
import jadx.core.dex.instructions.args.LiteralArg;
|
||||
import jadx.core.dex.instructions.args.PrimitiveType;
|
||||
@@ -81,7 +82,11 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
|
||||
resolved = false;
|
||||
}
|
||||
}
|
||||
if (!resolved) {
|
||||
if (resolved) {
|
||||
for (SSAVar var : new ArrayList<>(mth.getSVars())) {
|
||||
processIncompatiblePrimitives(mth, var);
|
||||
}
|
||||
} else {
|
||||
for (SSAVar var : new ArrayList<>(mth.getSVars())) {
|
||||
tryInsertAdditionalInsn(mth, var);
|
||||
}
|
||||
@@ -249,7 +254,7 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
|
||||
if (insn == null) {
|
||||
return null;
|
||||
}
|
||||
return new TypeBoundConst(BoundEnum.USE, regArg.getInitType());
|
||||
return new TypeBoundConst(BoundEnum.USE, regArg.getInitType(), regArg);
|
||||
}
|
||||
|
||||
private boolean tryPossibleTypes(SSAVar var, ArgType type) {
|
||||
@@ -375,4 +380,39 @@ public final class TypeInferenceVisitor extends AbstractVisitor {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void processIncompatiblePrimitives(MethodNode mth, SSAVar var) {
|
||||
if (var.getAssign().getType() == ArgType.BOOLEAN) {
|
||||
for (ITypeBound bound : var.getTypeInfo().getBounds()) {
|
||||
if (bound.getBound() == BoundEnum.USE
|
||||
&& bound.getType().isPrimitive() && bound.getType() != ArgType.BOOLEAN) {
|
||||
InsnNode insn = bound.getArg().getParentInsn();
|
||||
if (insn.getType() == InsnType.CAST) {
|
||||
continue;
|
||||
};
|
||||
|
||||
IndexInsnNode castNode = new IndexInsnNode(InsnType.CAST, bound.getType(), 1);
|
||||
castNode.addArg(bound.getArg());
|
||||
castNode.setResult(InsnArg.reg(bound.getArg().getRegNum(), bound.getType()));
|
||||
|
||||
SSAVar newVar = mth.makeNewSVar(castNode.getResult().getRegNum(), castNode.getResult());
|
||||
CodeVar codeVar = new CodeVar();
|
||||
codeVar.setType(bound.getType());
|
||||
newVar.setCodeVar(codeVar);
|
||||
newVar.getTypeInfo().setType(bound.getType());
|
||||
|
||||
for (int i = insn.getArgsCount() - 1; i >= 0; i--) {
|
||||
if (insn.getArg(i) == bound.getArg()) {
|
||||
insn.setArg(i, castNode.getResult().duplicate());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BlockNode blockNode = BlockUtils.getBlockByInsn(mth, insn);
|
||||
List<InsnNode> insnList = blockNode.getInstructions();
|
||||
insnList.add(insnList.indexOf(insn), castNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+4
-6
@@ -5,11 +5,10 @@ import static org.hamcrest.Matchers.containsString;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import jadx.NotYetImplemented;
|
||||
import jadx.core.dex.nodes.ClassNode;
|
||||
import jadx.tests.api.SmaliTest;
|
||||
|
||||
public class TestBooleanToInt2 extends SmaliTest {
|
||||
public class TestBooleanToInt extends SmaliTest {
|
||||
|
||||
/**
|
||||
private boolean showConsent;
|
||||
@@ -17,14 +16,13 @@ public class TestBooleanToInt2 extends SmaliTest {
|
||||
public void write(int b) {
|
||||
}
|
||||
|
||||
public void writeToParcel(TestBooleanToInt2 testBooleanToInt2) {
|
||||
testBooleanToInt2.write(this.showConsent ? 1 : 0);
|
||||
public void writeToParcel(TestBooleanToInt testBooleanToInt) {
|
||||
testBooleanToInt.write(this.showConsent ? 1 : 0);
|
||||
}
|
||||
*/
|
||||
@Test
|
||||
@NotYetImplemented
|
||||
public void test() {
|
||||
ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToInt2");
|
||||
ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToInt");
|
||||
String code = cls.getCode().toString();
|
||||
|
||||
assertThat(code, containsString("write(this.showConsent ? 1 : 0);"));
|
||||
@@ -0,0 +1,20 @@
|
||||
.class public LTestBooleanToInt;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.field private showConsent:Z
|
||||
|
||||
.method public writeToParcel(LTestBooleanToInt;)V
|
||||
.locals 0
|
||||
|
||||
iget-boolean p1, p0, LTestBooleanToInt;->showConsent:Z
|
||||
|
||||
invoke-virtual {p0, p1}, LTestBooleanToInt;->write(I)V
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public write(I)V
|
||||
.locals 0
|
||||
|
||||
return-void
|
||||
.end method
|
||||
@@ -1,20 +0,0 @@
|
||||
.class public LTestBooleanToInt2;
|
||||
.super Ljava/lang/Object;
|
||||
|
||||
.field private showConsent:Z
|
||||
|
||||
.method public writeToParcel(LTestBooleanToInt2;)V
|
||||
.locals 0
|
||||
|
||||
iget-boolean p1, p0, LTestBooleanToInt2;->showConsent:Z
|
||||
|
||||
invoke-virtual {p0, p1}, LTestBooleanToInt2;->write(I)V
|
||||
|
||||
return-void
|
||||
.end method
|
||||
|
||||
.method public write(I)V
|
||||
.locals 0
|
||||
|
||||
return-void
|
||||
.end method
|
||||
Reference in New Issue
Block a user