diff --git a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java index 21ec417976321a2787ee4e5f126a19b72c9ed13a..a33fc7c9a147831aecaf32fe6a85e61ebcb49791 100644 --- a/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java +++ b/jadx-core/src/main/java/jadx/core/codegen/InsnGen.java @@ -843,7 +843,7 @@ public class InsnGen { InsnArg first = insn.getArg(0); InsnArg second = insn.getArg(1); ConditionGen condGen = new ConditionGen(this); - if (first.equals(LiteralArg.TRUE) && second.equals(LiteralArg.FALSE)) { + if (first.isTrue() && second.isFalse()) { condGen.add(code, insn.getCondition()); } else { condGen.wrap(code, insn.getCondition()); diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java index 8794f2f0ed5bb3b0e69186efbcdbda39366b9f3c..ee7dff9e582cc18fc0a2a8360fb1f963dcdc317e 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/InsnArg.java @@ -1,5 +1,7 @@ package jadx.core.dex.instructions.args; +import java.util.Objects; + import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -56,7 +58,7 @@ public abstract class InsnArg extends Typed { } public static LiteralArg lit(long literal, ArgType type) { - return new LiteralArg(literal, type); + return LiteralArg.makeWithFixedType(literal, type); } public static LiteralArg lit(InsnData insn, ArgType type) { @@ -210,6 +212,22 @@ public abstract class InsnArg extends Typed { return isLiteral() && (((LiteralArg) this)).getLiteral() == 0; } + public boolean isFalse() { + if (isLiteral()) { + LiteralArg litArg = (LiteralArg) this; + return litArg.getLiteral() == 0 && Objects.equals(litArg.getType(), ArgType.BOOLEAN); + } + return false; + } + + public boolean isTrue() { + if (isLiteral()) { + LiteralArg litArg = (LiteralArg) this; + return litArg.getLiteral() == 1 && Objects.equals(litArg.getType(), ArgType.BOOLEAN); + } + return false; + } + public boolean isThis() { return contains(AFlag.THIS); } diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/args/LiteralArg.java b/jadx-core/src/main/java/jadx/core/dex/instructions/args/LiteralArg.java index 0c284fafbf5804544a005c3d39fbcd1aa9e20a3b..cc1697af4db3b3f725d19be0c51e10cc8fc544de 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/args/LiteralArg.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/args/LiteralArg.java @@ -6,24 +6,37 @@ import jadx.core.utils.exceptions.JadxRuntimeException; public final class LiteralArg extends InsnArg { - public static final LiteralArg TRUE = new LiteralArg(1, ArgType.BOOLEAN); - public static final LiteralArg FALSE = new LiteralArg(0, ArgType.BOOLEAN); + public static LiteralArg make(long value, ArgType type) { + return new LiteralArg(value, type); + } + + public static LiteralArg makeWithFixedType(long value, ArgType type) { + return new LiteralArg(value, fixLiteralType(value, type)); + } + + private static ArgType fixLiteralType(long value, ArgType type) { + if (value == 0 || type.isTypeKnown() || type.contains(PrimitiveType.LONG) || type.contains(PrimitiveType.DOUBLE)) { + return type; + } + if (value == 1) { + return ArgType.NARROW_NUMBERS; + } + return ArgType.NARROW_NUMBERS_NO_BOOL; + } + + public static LiteralArg litFalse() { + return new LiteralArg(0, ArgType.BOOLEAN); + } + + public static LiteralArg litTrue() { + return new LiteralArg(1, ArgType.BOOLEAN); + } private final long literal; - public LiteralArg(long value, ArgType type) { - if (value != 0) { - if (type.isObject()) { - throw new JadxRuntimeException("Wrong literal type: " + type + " for value: " + value); - } else if (!type.isTypeKnown() - && !type.contains(PrimitiveType.LONG) - && !type.contains(PrimitiveType.DOUBLE)) { - if (value != 1) { - type = ArgType.NARROW_NUMBERS_NO_BOOL; - } else { - type = ArgType.NARROW_NUMBERS; - } - } + private LiteralArg(long value, ArgType type) { + if (value != 0 && type.isObject()) { + throw new JadxRuntimeException("Wrong literal type: " + type + " for value: " + value); } this.literal = value; this.type = type; @@ -33,6 +46,11 @@ public final class LiteralArg extends InsnArg { return literal; } + @Override + public void setType(ArgType type) { + super.setType(type); + } + @Override public boolean isLiteral() { return true; @@ -49,9 +67,7 @@ public final class LiteralArg extends InsnArg { @Override public InsnArg duplicate() { - LiteralArg copy = new LiteralArg(literal, getType()); - copy.type = type; - return copyCommonParams(copy); + return copyCommonParams(new LiteralArg(literal, type)); } @Override diff --git a/jadx-core/src/main/java/jadx/core/dex/instructions/mods/TernaryInsn.java b/jadx-core/src/main/java/jadx/core/dex/instructions/mods/TernaryInsn.java index a16a5b99a109d87ed8ef685990d3188554b400bb..f80f2ccb4c3a68db76aac28c29e6cafdbbd49541 100644 --- a/jadx-core/src/main/java/jadx/core/dex/instructions/mods/TernaryInsn.java +++ b/jadx-core/src/main/java/jadx/core/dex/instructions/mods/TernaryInsn.java @@ -4,7 +4,6 @@ import java.util.Collection; import jadx.core.dex.instructions.InsnType; import jadx.core.dex.instructions.args.InsnArg; -import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.instructions.args.RegisterArg; import jadx.core.dex.nodes.InsnNode; import jadx.core.dex.regions.conditions.IfCondition; @@ -18,7 +17,7 @@ public final class TernaryInsn extends InsnNode { this(); setResult(result); - if (th.equals(LiteralArg.FALSE) && els.equals(LiteralArg.TRUE)) { + if (th.isFalse() && els.isTrue()) { // inverted this.condition = IfCondition.invert(condition); addArg(els); diff --git a/jadx-core/src/main/java/jadx/core/dex/regions/conditions/Compare.java b/jadx-core/src/main/java/jadx/core/dex/regions/conditions/Compare.java index b740a1ce597ff29858cb257ed961211715140142..03861a9ddaa8475ea0b5d8985f7decee26a012fd 100644 --- a/jadx-core/src/main/java/jadx/core/dex/regions/conditions/Compare.java +++ b/jadx-core/src/main/java/jadx/core/dex/regions/conditions/Compare.java @@ -39,8 +39,8 @@ public final class Compare { * Change 'a != false' to 'a == true' */ public void normalize() { - if (getOp() == IfOp.NE && getB().isLiteral() && getB().equals(LiteralArg.FALSE)) { - insn.changeCondition(IfOp.EQ, getA(), LiteralArg.TRUE); + if (getOp() == IfOp.NE && getB().isFalse()) { + insn.changeCondition(IfOp.EQ, getA(), LiteralArg.litTrue()); } } diff --git a/jadx-core/src/main/java/jadx/core/dex/regions/conditions/IfCondition.java b/jadx-core/src/main/java/jadx/core/dex/regions/conditions/IfCondition.java index b597116e9d3986cc8a566a2c9a58078ceaa1a08e..d8dbe0734f3d164236df0fbd6378d453efbcf464 100644 --- a/jadx-core/src/main/java/jadx/core/dex/regions/conditions/IfCondition.java +++ b/jadx-core/src/main/java/jadx/core/dex/regions/conditions/IfCondition.java @@ -153,7 +153,7 @@ public final class IfCondition extends AttrNode { if (i != null) { return i; } - if (c.getOp() == IfOp.EQ && c.getB().isLiteral() && c.getB().equals(LiteralArg.FALSE)) { + if (c.getOp() == IfOp.EQ && c.getB().isFalse()) { cond = not(new IfCondition(c.invert())); } else { c.normalize(); @@ -234,8 +234,8 @@ public final class IfCondition extends AttrNode { Mode mode = isTrue && arithOp == ArithOp.OR || !isTrue && arithOp == ArithOp.AND ? Mode.OR : Mode.AND; - IfNode if1 = new IfNode(op, -1, wrapInsn.getArg(0), LiteralArg.FALSE); - IfNode if2 = new IfNode(op, -1, wrapInsn.getArg(1), LiteralArg.FALSE); + IfNode if1 = new IfNode(op, -1, wrapInsn.getArg(0), LiteralArg.litFalse()); + IfNode if2 = new IfNode(op, -1, wrapInsn.getArg(1), LiteralArg.litFalse()); return new IfCondition(mode, Arrays.asList(new IfCondition(new Compare(if1)), new IfCondition(new Compare(if2)))); diff --git a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java index 335954159c767efd547624047ff987a75aaa7f5e..c6f174580d486a23274435201e593ee2c1b78759 100644 --- a/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java +++ b/jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java @@ -253,16 +253,16 @@ public class ModVisitor extends AbstractVisitor { } public static TernaryInsn makeBooleanConvertInsn(RegisterArg result, InsnArg castArg, ArgType type) { - InsnArg zero = new LiteralArg(0, type); + InsnArg zero = LiteralArg.make(0, type); long litVal = 1; if (type == ArgType.DOUBLE) { litVal = DOUBLE_TO_BITS; } else if (type == ArgType.FLOAT) { litVal = FLOAT_TO_BITS; } - InsnArg one = new LiteralArg(litVal, type); + InsnArg one = LiteralArg.make(litVal, type); - IfNode ifNode = new IfNode(IfOp.EQ, -1, castArg, LiteralArg.TRUE); + IfNode ifNode = new IfNode(IfOp.EQ, -1, castArg, LiteralArg.litTrue()); IfCondition condition = IfCondition.fromIfNode(ifNode); return new TernaryInsn(condition, result, one, zero); } diff --git a/jadx-core/src/main/java/jadx/core/utils/EncodedValueUtils.java b/jadx-core/src/main/java/jadx/core/utils/EncodedValueUtils.java index f9595b755cb8f80d37b7afbff43f9483add284af..c3bac8a18622d5938d04e8a750d22fd9a2768c1f 100644 --- a/jadx-core/src/main/java/jadx/core/utils/EncodedValueUtils.java +++ b/jadx-core/src/main/java/jadx/core/utils/EncodedValueUtils.java @@ -25,7 +25,7 @@ public class EncodedValueUtils { case ENCODED_NULL: return InsnArg.lit(0, ArgType.OBJECT); case ENCODED_BOOLEAN: - return Boolean.TRUE.equals(value) ? LiteralArg.TRUE : LiteralArg.FALSE; + return Boolean.TRUE.equals(value) ? LiteralArg.litTrue() : LiteralArg.litFalse(); case ENCODED_BYTE: return InsnArg.lit((Byte) value, ArgType.BYTE); case ENCODED_SHORT: diff --git a/jadx-core/src/test/java/jadx/tests/functional/TestIfCondition.java b/jadx-core/src/test/java/jadx/tests/functional/TestIfCondition.java index b74782976b8b022c7a9cba2934bd7bf45b8de9ad..4422c79b98a47ef897ef56eb140063552e7b857f 100644 --- a/jadx-core/src/test/java/jadx/tests/functional/TestIfCondition.java +++ b/jadx-core/src/test/java/jadx/tests/functional/TestIfCondition.java @@ -10,7 +10,6 @@ import jadx.core.dex.instructions.args.LiteralArg; import jadx.core.dex.regions.conditions.Compare; import jadx.core.dex.regions.conditions.IfCondition; -import static jadx.core.dex.instructions.args.LiteralArg.TRUE; import static jadx.core.dex.regions.conditions.IfCondition.Mode; import static jadx.core.dex.regions.conditions.IfCondition.Mode.AND; import static jadx.core.dex.regions.conditions.IfCondition.Mode.COMPARE; @@ -29,11 +28,11 @@ public class TestIfCondition { } private static IfCondition makeSimpleCondition() { - return makeCondition(IfOp.EQ, mockArg(), LiteralArg.TRUE); + return makeCondition(IfOp.EQ, mockArg(), LiteralArg.litTrue()); } private static IfCondition makeNegCondition() { - return makeCondition(IfOp.NE, mockArg(), LiteralArg.TRUE); + return makeCondition(IfOp.NE, mockArg(), LiteralArg.litTrue()); } private static InsnArg mockArg() { @@ -44,13 +43,13 @@ public class TestIfCondition { public void testNormalize() { // 'a != false' => 'a == true' InsnArg a = mockArg(); - IfCondition c = makeCondition(IfOp.NE, a, LiteralArg.FALSE); + IfCondition c = makeCondition(IfOp.NE, a, LiteralArg.litFalse()); IfCondition simp = simplify(c); assertThat(simp.getMode(), is(COMPARE)); Compare compare = simp.getCompare(); assertThat(compare.getA(), is(a)); - assertThat(compare.getB(), is(TRUE)); + assertThat(compare.getB(), is(LiteralArg.litTrue())); } @Test