From bfd60b733a2ed0275db161a190aebc41e4fa1979 Mon Sep 17 00:00:00 2001 From: Skylot Date: Tue, 4 Aug 2020 12:26:31 +0100 Subject: [PATCH] fix: handle method arguments in primitive types conversion (#956) --- .../dex/instructions/args/RegisterArg.java | 8 ++---- .../core/dex/instructions/args/SSAVar.java | 20 +++++++++++-- .../typeinference/TypeInferenceVisitor.java | 12 ++------ .../types/TestPrimitiveConversion.java | 28 +++++++++++++++++++ .../smali/types/TestPrimitiveConversion.smali | 15 ++++++++++ 5 files changed, 66 insertions(+), 17 deletions(-) create mode 100644 jadx-core/src/test/java/jadx/tests/integration/types/TestPrimitiveConversion.java create mode 100644 jadx-core/src/test/smali/types/TestPrimitiveConversion.smali diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java index 92c49fab5..1286e323f 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/RegisterArg.java @@ -52,12 +52,8 @@ public class RegisterArg extends InsnArg implements Named { sVar.setType(newType); } - public void updateImmutableType(ArgType type) { - if (sVar == null) { - throw new JadxRuntimeException("Unknown SSA variable to update immutable type: " + this); - } - sVar.forceSetType(type); - sVar.getAssign().add(AFlag.IMMUTABLE_TYPE); + public void forceSetInitType(ArgType type) { + this.type = type; } @Nullable diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java index 58fc0a95a..f48d9ee34 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/SSAVar.java @@ -8,7 +8,10 @@ import java.util.Set; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import jadx.core.Consts; import jadx.core.dex.attributes.AFlag; import jadx.core.dex.attributes.AType; import jadx.core.dex.attributes.nodes.RegDebugInfoAttr; @@ -21,6 +24,8 @@ import jadx.core.utils.StringUtils; import jadx.core.utils.exceptions.JadxRuntimeException; public class SSAVar { + private static final Logger LOG = LoggerFactory.getLogger(SSAVar.class); + private final int regNum; private final int version; @@ -68,8 +73,8 @@ public class SSAVar { @Nullable public ArgType getImmutableType() { - if (assign.contains(AFlag.IMMUTABLE_TYPE)) { - return assign.getType(); + if (isTypeImmutable()) { + return assign.getInitType(); } return null; } @@ -78,6 +83,17 @@ public class SSAVar { return assign.contains(AFlag.IMMUTABLE_TYPE); } + public void markAsImmutable(ArgType type) { + assign.add(AFlag.IMMUTABLE_TYPE); + ArgType initType = assign.getInitType(); + if (!initType.equals(type)) { + assign.forceSetInitType(type); + if (Consts.DEBUG_TYPE_INFERENCE) { + LOG.debug("Update immutable type at var {} assign with type: {} previous type: {}", this.toShortString(), type, initType); + } + } + } + public void setType(ArgType type) { ArgType imType = getImmutableType(); if (imType != null && !imType.equals(type)) { diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java index 41e6d417e..64df139c6 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/typeinference/TypeInferenceVisitor.java @@ -803,21 +803,15 @@ public final class TypeInferenceVisitor extends AbstractVisitor { private static void assignImmutableTypes(MethodNode mth) { for (SSAVar ssaVar : mth.getSVars()) { - ArgType imType = getSsaImmutableType(ssaVar); - if (imType != null) { - ssaVar.getAssign().updateImmutableType(imType); + ArgType immutableType = getSsaImmutableType(ssaVar); + if (immutableType != null) { + ssaVar.markAsImmutable(immutableType); } } } @Nullable private static ArgType getSsaImmutableType(SSAVar ssaVar) { - if (ssaVar.isTypeImmutable()) { - ArgType type = ssaVar.getTypeInfo().getType(); - if (type != ArgType.UNKNOWN) { - return type; - } - } if (ssaVar.getAssign().contains(AFlag.IMMUTABLE_TYPE)) { return ssaVar.getAssign().getInitType(); } diff --git a/jadx-core/src/test/java/jadx/tests/integration/types/TestPrimitiveConversion.java b/jadx-core/src/test/java/jadx/tests/integration/types/TestPrimitiveConversion.java new file mode 100644 index 000000000..67dd9a723 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/types/TestPrimitiveConversion.java @@ -0,0 +1,28 @@ +package jadx.tests.integration.types; + +import org.junit.jupiter.api.Test; + +import jadx.tests.api.SmaliTest; + +import static jadx.tests.api.utils.assertj.JadxAssertions.assertThat; + +public class TestPrimitiveConversion extends SmaliTest { + // @formatter:off + /* + public void test(long j, boolean z) { + putByte(j, z ? (byte) 1 : (byte) 0); + } + + private static void putByte(long j, byte z) { + } + */ + // @formatter:on + + @Test + public void test() { + assertThat(getClassNodeFromSmali()) + .code() + .doesNotContain("putByte(j, z);") + .containsOne("putByte(j, z ? (byte) 1 : 0);"); + } +} diff --git a/jadx-core/src/test/smali/types/TestPrimitiveConversion.smali b/jadx-core/src/test/smali/types/TestPrimitiveConversion.smali new file mode 100644 index 000000000..3a275c0e2 --- /dev/null +++ b/jadx-core/src/test/smali/types/TestPrimitiveConversion.smali @@ -0,0 +1,15 @@ +.class public Ltypes/TestPrimitiveConversion; +.super Ljava/lang/Object; + +.method public test(JZ)V + .registers 5 + + invoke-static {p1, p2, p3}, Ltypes/TestPrimitiveConversion;->putByte(JB)V + return-void +.end method + +.method private static putByte(JB)V + .registers 3 + + return-void +.end method