Skip to content

Commit

Permalink
fix: conditions in ternary if (#449) (PR #558)
Browse files Browse the repository at this point in the history
  • Loading branch information
asashour authored and skylot committed Apr 12, 2019
1 parent ac1d1a5 commit eb77aa5
Show file tree
Hide file tree
Showing 4 changed files with 217 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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;
Expand Down Expand Up @@ -118,7 +119,7 @@ public static IfCondition invert(IfCondition cond) {
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:
Expand All @@ -137,6 +138,9 @@ public static IfCondition not(IfCondition cond) {
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));
}

Expand Down Expand Up @@ -281,4 +285,30 @@ public String toString() {
}
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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public boolean test1(boolean a, boolean b, boolean c) {
}

public int test2(boolean a, boolean b, boolean c) {
return (a ? b : c) ? 1 : 2;
return (!a ? c : b) ? 1 : 2;
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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");
}
}
143 changes: 143 additions & 0 deletions jadx-core/src/test/smali/conditions/TestTernaryInIf2.smali
Original file line number Diff line number Diff line change
@@ -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 <init>()V
.locals 0

.line 10
invoke-direct {p0}, Ljava/lang/Object;-><init>()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

0 comments on commit eb77aa5

Please sign in to comment.