Skip to content

Commit

Permalink
fix: cast of int-to-(number) when int is boolean (#596) (PR #602)
Browse files Browse the repository at this point in the history
  • Loading branch information
asashour authored and skylot committed Apr 20, 2019
1 parent 2148d4b commit c134329
Show file tree
Hide file tree
Showing 14 changed files with 343 additions and 2 deletions.
8 changes: 8 additions & 0 deletions jadx-core/src/main/java/jadx/core/codegen/InsnGen.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import org.slf4j.LoggerFactory;

import jadx.core.Consts;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.AFlag;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.nodes.FieldReplaceAttr;
Expand Down Expand Up @@ -888,6 +889,13 @@ private void addCastIfNeeded(CodeWriter code, InsnArg first, InsnArg second) {
&& lit2 != Short.MAX_VALUE && lit2 != Short.MIN_VALUE) {
code.add("(short) ");
}
} else if (first.getType() == ArgType.CHAR) {
long lit1 = ((LiteralArg) first).getLiteral();
long lit2 = ((LiteralArg) second).getLiteral();
if (!NameMapper.isPrintableChar((char) (lit1))
&& !NameMapper.isPrintableChar((char) (lit2))) {
code.add("(char) ");
}
}
}
}
Expand Down
25 changes: 23 additions & 2 deletions jadx-core/src/main/java/jadx/core/dex/visitors/ModVisitor.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package jadx.core.dex.visitors;

import static jadx.core.utils.BlockUtils.replaceInsn;

import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
Expand All @@ -18,6 +20,8 @@
import jadx.core.dex.instructions.ConstStringNode;
import jadx.core.dex.instructions.FillArrayNode;
import jadx.core.dex.instructions.FilledNewArrayNode;
import jadx.core.dex.instructions.IfNode;
import jadx.core.dex.instructions.IfOp;
import jadx.core.dex.instructions.IndexInsnNode;
import jadx.core.dex.instructions.InsnType;
import jadx.core.dex.instructions.NewArrayNode;
Expand All @@ -29,11 +33,13 @@
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.instructions.mods.ConstructorInsn;
import jadx.core.dex.instructions.mods.TernaryInsn;
import jadx.core.dex.nodes.BlockNode;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.regions.conditions.IfCondition;
import jadx.core.dex.trycatch.ExcHandlerAttr;
import jadx.core.dex.trycatch.ExceptionHandler;
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
Expand All @@ -42,8 +48,6 @@
import jadx.core.utils.InsnUtils;
import jadx.core.utils.exceptions.JadxRuntimeException;

import static jadx.core.utils.BlockUtils.replaceInsn;

/**
* Visitor for modify method instructions
* (remove, replace, process exception handlers)
Expand Down Expand Up @@ -155,6 +159,23 @@ private static void replaceStep(MethodNode mth, InsnRemover remover) {
}
break;

case CAST:
// replace boolean to (byte/char/short/long/double/float) cast with ternary
if (insn.getArg(0).getType() == ArgType.BOOLEAN) {
ArgType type = insn.getResult().getType();
if (type.isPrimitive()) {
IfNode ifNode = new IfNode(IfOp.EQ, -1, insn.getArg(0), LiteralArg.TRUE);
IfCondition condition = IfCondition.fromIfNode(ifNode);
InsnArg zero = new LiteralArg(0, type);
InsnArg one = new LiteralArg(
type == ArgType.DOUBLE ? Double.doubleToLongBits(1) :
type == ArgType.FLOAT ? Float.floatToIntBits(1) : 1, type);
TernaryInsn ternary = new TernaryInsn(condition, insn.getResult(), one, zero);
replaceInsn(block, i, ternary);
}
}
break;

default:
break;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package jadx.tests.integration.conditions;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;

import org.junit.jupiter.api.Test;

import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;

public class TestBooleanToByte extends SmaliTest {

/**
private boolean showConsent;
public void write(byte b) {
}
public void writeToParcel(TestBooleanToByte testBooleanToByte) {
testBooleanToByte.write(this.showConsent ? (byte) 1 : 0);
}
*/
@Test
public void test() {
ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToByte");
String code = cls.getCode().toString();

assertThat(code, containsString("write(this.showConsent ? (byte) 1 : 0);"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package jadx.tests.integration.conditions;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;

import org.junit.jupiter.api.Test;

import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;

public class TestBooleanToChar extends SmaliTest {

/**
private boolean showConsent;
public void write(char b) {
}
public void writeToParcel(TestBooleanToChar testBooleanToChar) {
testBooleanToChar.write(this.showConsent ? (char) 1 : 0);
}
*/
@Test
public void test() {
ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToChar");
String code = cls.getCode().toString();

assertThat(code, containsString("write(this.showConsent ? (char) 1 : 0);"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package jadx.tests.integration.conditions;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;

import org.junit.jupiter.api.Test;

import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;

public class TestBooleanToDouble extends SmaliTest {

/**
private boolean showConsent;
public void write(double d) {
}
public void writeToParcel(TestBooleanToDouble testBooleanToDouble) {
testBooleanToDouble.write(this.showConsent ? 1 : 0);
}
*/
@Test
public void test() {
ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToDouble");
String code = cls.getCode().toString();

assertThat(code, containsString("write(this.showConsent ? 1.0d : 0.0d);"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package jadx.tests.integration.conditions;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;

import org.junit.jupiter.api.Test;

import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;

public class TestBooleanToFloat extends SmaliTest {

/**
private boolean showConsent;
public void write(float f) {
}
public void writeToParcel(TestBooleanToFloat testBooleanToFloat) {
testBooleanToFloat.write(this.showConsent ? 1 : 0);
}
*/
@Test
public void test() {
ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToFloat");
String code = cls.getCode().toString();

assertThat(code, containsString("write(this.showConsent ? 1.0f : 0.0f);"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package jadx.tests.integration.conditions;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;

import org.junit.jupiter.api.Test;

import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;

public class TestBooleanToLong extends SmaliTest {

/**
private boolean showConsent;
public void write(long j) {
}
public void writeToParcel(TestBooleanToLong testBooleanToLong) {
testBooleanToLong.write(this.showConsent ? 1 : 0);
}
*/
@Test
public void test() {
ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToLong");
String code = cls.getCode().toString();

assertThat(code, containsString("write(this.showConsent ? 1 : 0);"));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package jadx.tests.integration.conditions;

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;

import org.junit.jupiter.api.Test;

import jadx.core.dex.nodes.ClassNode;
import jadx.tests.api.SmaliTest;

public class TestBooleanToShort extends SmaliTest {

/**
private boolean showConsent;
public void write(short b) {
}
public void writeToParcel(TestBooleanToShort testBooleanToShort) {
testBooleanToShort.write(this.showConsent ? (short) 1 : 0);
}
*/
@Test
public void test() {
ClassNode cls = getClassNodeFromSmaliWithPath("conditions", "TestBooleanToShort");
String code = cls.getCode().toString();

assertThat(code, containsString("write(this.showConsent ? (short) 1 : 0);"));
}
}
22 changes: 22 additions & 0 deletions jadx-core/src/test/smali/conditions/TestBooleanToByte.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.class public LTestBooleanToByte;
.super Ljava/lang/Object;

.field private showConsent:Z

.method public writeToParcel(LTestBooleanToByte;)V
.locals 0

iget-boolean p1, p0, LTestBooleanToByte;->showConsent:Z

int-to-byte p1, p1

invoke-virtual {p0, p1}, LTestBooleanToByte;->write(B)V

return-void
.end method

.method public write(B)V
.locals 0

return-void
.end method
22 changes: 22 additions & 0 deletions jadx-core/src/test/smali/conditions/TestBooleanToChar.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.class public LTestBooleanToChar;
.super Ljava/lang/Object;

.field private showConsent:Z

.method public writeToParcel(LTestBooleanToChar;)V
.locals 0

iget-boolean p1, p0, LTestBooleanToChar;->showConsent:Z

int-to-char p1, p1

invoke-virtual {p0, p1}, LTestBooleanToChar;->write(C)V

return-void
.end method

.method public write(C)V
.locals 0

return-void
.end method
22 changes: 22 additions & 0 deletions jadx-core/src/test/smali/conditions/TestBooleanToDouble.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.class public LTestBooleanToDouble;
.super Ljava/lang/Object;

.field private showConsent:Z

.method public writeToParcel(LTestBooleanToDouble;)V
.locals 0

iget-boolean p1, p0, LTestBooleanToDouble;->showConsent:Z

int-to-double p1, p1

invoke-virtual {p0, p1}, LTestBooleanToDouble;->write(D)V

return-void
.end method

.method public write(D)V
.locals 0

return-void
.end method
22 changes: 22 additions & 0 deletions jadx-core/src/test/smali/conditions/TestBooleanToFloat.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.class public LTestBooleanToFloat;
.super Ljava/lang/Object;

.field private showConsent:Z

.method public writeToParcel(LTestBooleanToFloat;)V
.locals 0

iget-boolean p1, p0, LTestBooleanToFloat;->showConsent:Z

int-to-float p1, p1

invoke-virtual {p0, p1}, LTestBooleanToFloat;->write(F)V

return-void
.end method

.method public write(F)V
.locals 0

return-void
.end method
22 changes: 22 additions & 0 deletions jadx-core/src/test/smali/conditions/TestBooleanToLong.smali
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
.class public LTestBooleanToLong;
.super Ljava/lang/Object;

.field private showConsent:Z

.method public writeToParcel(LTestBooleanToLong;)V
.locals 0

iget-boolean p1, p0, LTestBooleanToLong;->showConsent:Z

int-to-long p1, p1

invoke-virtual {p0, p1}, LTestBooleanToLong;->write(J)V

return-void
.end method

.method public write(J)V
.locals 0

return-void
.end method
Loading

0 comments on commit c134329

Please sign in to comment.