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 907a383ee..0df67f8fe 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 @@ -6,6 +6,7 @@ import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; +import java.util.Objects; import jadx.core.dex.instructions.ArithNode; import jadx.core.dex.instructions.ArithOp; @@ -118,7 +119,7 @@ public final class IfCondition { case COMPARE: return new IfCondition(cond.getCompare().invert()); case TERNARY: - return ternary(not(cond.first()), cond.third(), cond.second()); + return ternary(cond.first(), not(cond.second()), not(cond.third())); case NOT: return cond.first(); case AND: @@ -137,6 +138,9 @@ public final class IfCondition { if (cond.getMode() == Mode.NOT) { return cond.first(); } + if (cond.getCompare() != null) { + return new IfCondition(cond.compare.invert()); + } return new IfCondition(Mode.NOT, Collections.singletonList(cond)); } @@ -281,4 +285,30 @@ public final class IfCondition { } return "??"; } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof IfCondition)) { + return false; + } + IfCondition other = (IfCondition) obj; + if (mode != other.mode) { + return false; + } + return Objects.equals(other.args, other.args) + && Objects.equals(compare, other.compare); + } + + @Override + public int hashCode() { + int result = super.hashCode(); + result = 31 * result + mode.hashCode(); + result = 31 * result + args.hashCode(); + result = 31 * result + (compare != null ? compare.hashCode() : 0); + return result; + } + } diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf.java index c8f56e0f1..aa207e631 100644 --- a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf.java +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf.java @@ -18,7 +18,7 @@ public class TestTernaryInIf extends IntegrationTest { } public int test2(boolean a, boolean b, boolean c) { - return (a ? b : c) ? 1 : 2; + return (!a ? c : b) ? 1 : 2; } } diff --git a/jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf2.java b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf2.java new file mode 100644 index 000000000..42265f7c6 --- /dev/null +++ b/jadx-core/src/test/java/jadx/tests/integration/conditions/TestTernaryInIf2.java @@ -0,0 +1,42 @@ +package jadx.tests.integration.conditions; + +import static jadx.tests.api.utils.JadxMatchers.containsLines; +import static org.hamcrest.MatcherAssert.assertThat; + +import org.junit.jupiter.api.Test; + +import jadx.core.dex.nodes.ClassNode; +import jadx.tests.api.SmaliTest; + +public class TestTernaryInIf2 extends SmaliTest { + + public static class TestCls { + private String a; + private String b; + + public boolean equals(TestCls other) { + if (this.a == null ? other.a == null : this.a.equals(other.a)) { + if (this.b == null ? other.b == null : this.b.equals(other.b)) { + return true; + } + } + return false; + } + } + + @Test + public void test() { + ClassNode cls = getClassNode(TestCls.class); + String code = cls.getCode().toString(); + + assertThat(code, containsLines(2, "if (this.a != null ? this.a.equals(other.a) : other.a == null) {")); + assertThat(code, containsLines(3, "if (this.b != null ? this.b.equals(other.b) : other.b == null) {")); + assertThat(code, containsLines(4, "return true;")); + assertThat(code, containsLines(2, "return false;")); + } + + @Test + public void test2() { + getClassNodeFromSmaliWithPath("conditions", "TestTernaryInIf2"); + } +} diff --git a/jadx-core/src/test/smali/conditions/TestTernaryInIf2.smali b/jadx-core/src/test/smali/conditions/TestTernaryInIf2.smali new file mode 100644 index 000000000..d6fb35105 --- /dev/null +++ b/jadx-core/src/test/smali/conditions/TestTernaryInIf2.smali @@ -0,0 +1,143 @@ +.class public LTestTernaryInIf2; +.super Ljava/lang/Object; + + +# instance fields +.field private a:Ljava/lang/String; + +.field private b:Ljava/lang/String; + +.field private c:Ljava/lang/String; + +# direct methods +.method public constructor ()V + .locals 0 + + .line 10 + invoke-direct {p0}, Ljava/lang/Object;->()V + + return-void +.end method + + +# virtual methods +.method public equals(Ljava/lang/Object;)Z + .locals 4 + + const/4 v0, 0x1 + + if-ne p0, p1, :cond_0 + + return v0 + + :cond_0 + const/4 v1, 0x0 + + if-eqz p1, :cond_a + + .line 110 + invoke-virtual {p0}, Ljava/lang/Object;->getClass()Ljava/lang/Class; + + move-result-object v2 + + invoke-virtual {p1}, Ljava/lang/Object;->getClass()Ljava/lang/Class; + + move-result-object v3 + + if-eq v2, v3, :cond_1 + + goto :goto_4 + + .line 112 + :cond_1 + check-cast p1, LTestTernaryInIf2; + + .line 114 + iget-object v2, p0, LTestTernaryInIf2;->a:Ljava/lang/String; + + if-eqz v2, :cond_2 + + iget-object v2, p0, LTestTernaryInIf2;->a:Ljava/lang/String; + + iget-object v3, p1, LTestTernaryInIf2;->a:Ljava/lang/String; + + invoke-virtual {v2, v3}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z + + move-result v2 + + if-nez v2, :cond_3 + + goto :goto_0 + + :cond_2 + iget-object v2, p1, LTestTernaryInIf2;->a:Ljava/lang/String; + + if-eqz v2, :cond_3 + + :goto_0 + return v1 + + .line 116 + :cond_3 + iget-object v2, p0, LTestTernaryInIf2;->b:Ljava/lang/String; + + if-eqz v2, :cond_4 + + iget-object v2, p0, LTestTernaryInIf2;->b:Ljava/lang/String; + + iget-object v3, p1, LTestTernaryInIf2;->b:Ljava/lang/String; + + invoke-virtual {v2, v3}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z + + move-result v2 + + if-nez v2, :cond_5 + + goto :goto_1 + + :cond_4 + iget-object v2, p1, LTestTernaryInIf2;->b:Ljava/lang/String; + + if-eqz v2, :cond_5 + + :goto_1 + return v1 + + .line 118 + :cond_5 + iget-object v2, p0, LTestTernaryInIf2;->c:Ljava/lang/String; + + if-eqz v2, :cond_6 + + iget-object v2, p0, LTestTernaryInIf2;->c:Ljava/lang/String; + + iget-object v3, p1, LTestTernaryInIf2;->c:Ljava/lang/String; + + invoke-virtual {v2, v3}, Ljava/lang/String;->equals(Ljava/lang/Object;)Z + + move-result v2 + + if-nez v2, :cond_7 + + return v1 + + + :cond_6 + iget-object v2, p1, LTestTernaryInIf2;->c:Ljava/lang/String; + + if-eqz v2, :cond_7 + + .line 120 + :cond_7 + + :cond_8 + const/4 v0, 0x0 + + :goto_3 + return v0 + + :cond_a + :goto_4 + return v1 +.end method +