core: fix missing parenthesis in conditions
This commit is contained in:
@@ -16,6 +16,8 @@ import jadx.core.utils.exceptions.CodegenException;
|
|||||||
import jadx.core.utils.exceptions.JadxRuntimeException;
|
import jadx.core.utils.exceptions.JadxRuntimeException;
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.Queue;
|
||||||
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
@@ -23,46 +25,83 @@ import org.slf4j.LoggerFactory;
|
|||||||
public class ConditionGen extends InsnGen {
|
public class ConditionGen extends InsnGen {
|
||||||
private static final Logger LOG = LoggerFactory.getLogger(ConditionGen.class);
|
private static final Logger LOG = LoggerFactory.getLogger(ConditionGen.class);
|
||||||
|
|
||||||
|
private static class CondStack {
|
||||||
|
private final Queue<IfCondition> stack = new LinkedList<IfCondition>();
|
||||||
|
|
||||||
|
public Queue<IfCondition> getStack() {
|
||||||
|
return stack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void push(IfCondition cond) {
|
||||||
|
stack.add(cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IfCondition pop() {
|
||||||
|
return stack.poll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ConditionGen(InsnGen insnGen) {
|
public ConditionGen(InsnGen insnGen) {
|
||||||
super(insnGen.mgen, insnGen.fallback);
|
super(insnGen.mgen, insnGen.fallback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add(CodeWriter code, IfCondition condition) throws CodegenException {
|
void add(CodeWriter code, IfCondition condition) throws CodegenException {
|
||||||
|
add(code, new CondStack(), condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
void wrap(CodeWriter code, IfCondition condition) throws CodegenException {
|
||||||
|
wrap(code, new CondStack(), condition);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void add(CodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
|
||||||
|
stack.push(condition);
|
||||||
switch (condition.getMode()) {
|
switch (condition.getMode()) {
|
||||||
case COMPARE:
|
case COMPARE:
|
||||||
addCompare(code, condition.getCompare());
|
addCompare(code, stack, condition.getCompare());
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TERNARY:
|
case TERNARY:
|
||||||
addTernary(code, condition);
|
addTernary(code, stack, condition);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case NOT:
|
case NOT:
|
||||||
addNot(code, condition);
|
addNot(code, stack, condition);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AND:
|
case AND:
|
||||||
case OR:
|
case OR:
|
||||||
addAndOr(code, condition);
|
addAndOr(code, stack, condition);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new JadxRuntimeException("Unknown condition mode: " + condition.getMode());
|
throw new JadxRuntimeException("Unknown condition mode: " + condition.getMode());
|
||||||
}
|
}
|
||||||
|
stack.pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
void wrap(CodeWriter code, IfCondition cond) throws CodegenException {
|
private void wrap(CodeWriter code, CondStack stack, IfCondition cond) throws CodegenException {
|
||||||
boolean wrap = isWrapNeeded(cond);
|
boolean wrap = isWrapNeeded(cond);
|
||||||
if (wrap) {
|
if (wrap) {
|
||||||
code.add('(');
|
code.add('(');
|
||||||
}
|
}
|
||||||
add(code, cond);
|
add(code, stack, cond);
|
||||||
if (wrap) {
|
if (wrap) {
|
||||||
code.add(')');
|
code.add(')');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addCompare(CodeWriter code, Compare compare) throws CodegenException {
|
private void wrap(CodeWriter code, InsnArg firstArg) throws CodegenException {
|
||||||
|
boolean wrap = isArgWrapNeeded(firstArg);
|
||||||
|
if (wrap) {
|
||||||
|
code.add('(');
|
||||||
|
}
|
||||||
|
addArg(code, firstArg, false);
|
||||||
|
if (wrap) {
|
||||||
|
code.add(')');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addCompare(CodeWriter code, CondStack stack, Compare compare) throws CodegenException {
|
||||||
IfOp op = compare.getOp();
|
IfOp op = compare.getOp();
|
||||||
InsnArg firstArg = compare.getA();
|
InsnArg firstArg = compare.getA();
|
||||||
InsnArg secondArg = compare.getB();
|
InsnArg secondArg = compare.getB();
|
||||||
@@ -75,19 +114,16 @@ public class ConditionGen extends InsnGen {
|
|||||||
}
|
}
|
||||||
if (op == IfOp.EQ) {
|
if (op == IfOp.EQ) {
|
||||||
// == true
|
// == true
|
||||||
addArg(code, firstArg, false);
|
if (stack.getStack().size() == 1) {
|
||||||
|
addArg(code, firstArg, false);
|
||||||
|
} else {
|
||||||
|
wrap(code, firstArg);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
} else if (op == IfOp.NE) {
|
} else if (op == IfOp.NE) {
|
||||||
// != true
|
// != true
|
||||||
code.add('!');
|
code.add('!');
|
||||||
boolean wrap = isArgWrapNeeded(firstArg);
|
wrap(code, firstArg);
|
||||||
if (wrap) {
|
|
||||||
code.add('(');
|
|
||||||
}
|
|
||||||
addArg(code, firstArg, false);
|
|
||||||
if (wrap) {
|
|
||||||
code.add(')');
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
LOG.warn(ErrorsCounter.formatErrorMsg(mth, "Unsupported boolean condition " + op.getSymbol()));
|
LOG.warn(ErrorsCounter.formatErrorMsg(mth, "Unsupported boolean condition " + op.getSymbol()));
|
||||||
@@ -98,24 +134,24 @@ public class ConditionGen extends InsnGen {
|
|||||||
addArg(code, secondArg, isArgWrapNeeded(secondArg));
|
addArg(code, secondArg, isArgWrapNeeded(secondArg));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addTernary(CodeWriter code, IfCondition condition) throws CodegenException {
|
private void addTernary(CodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
|
||||||
add(code, condition.first());
|
add(code, stack, condition.first());
|
||||||
code.add(" ? ");
|
code.add(" ? ");
|
||||||
add(code, condition.second());
|
add(code, stack, condition.second());
|
||||||
code.add(" : ");
|
code.add(" : ");
|
||||||
add(code, condition.third());
|
add(code, stack, condition.third());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addNot(CodeWriter code, IfCondition condition) throws CodegenException {
|
private void addNot(CodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
|
||||||
code.add('!');
|
code.add('!');
|
||||||
wrap(code, condition.getArgs().get(0));
|
wrap(code, stack, condition.getArgs().get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addAndOr(CodeWriter code, IfCondition condition) throws CodegenException {
|
private void addAndOr(CodeWriter code, CondStack stack, IfCondition condition) throws CodegenException {
|
||||||
String mode = condition.getMode() == Mode.AND ? " && " : " || ";
|
String mode = condition.getMode() == Mode.AND ? " && " : " || ";
|
||||||
Iterator<IfCondition> it = condition.getArgs().iterator();
|
Iterator<IfCondition> it = condition.getArgs().iterator();
|
||||||
while (it.hasNext()) {
|
while (it.hasNext()) {
|
||||||
wrap(code, it.next());
|
wrap(code, stack, it.next());
|
||||||
if (it.hasNext()) {
|
if (it.hasNext()) {
|
||||||
code.add(mode);
|
code.add(mode);
|
||||||
}
|
}
|
||||||
@@ -123,7 +159,13 @@ public class ConditionGen extends InsnGen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private boolean isWrapNeeded(IfCondition condition) {
|
private boolean isWrapNeeded(IfCondition condition) {
|
||||||
return !condition.isCompare() && condition.getMode() != Mode.NOT;
|
if (condition.isCompare()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (condition.getMode() != Mode.NOT) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean isArgWrapNeeded(InsnArg arg) {
|
private static boolean isArgWrapNeeded(InsnArg arg) {
|
||||||
|
|||||||
@@ -140,9 +140,8 @@ public class RegionMaker {
|
|||||||
}
|
}
|
||||||
if (next != null && !stack.containsExit(block) && !stack.containsExit(next)) {
|
if (next != null && !stack.containsExit(block) && !stack.containsExit(next)) {
|
||||||
return next;
|
return next;
|
||||||
} else {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private BlockNode processLoop(IRegion curRegion, LoopInfo loop, RegionStack stack) {
|
private BlockNode processLoop(IRegion curRegion, LoopInfo loop, RegionStack stack) {
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package jadx.tests.integration.conditions;
|
||||||
|
|
||||||
|
import jadx.core.dex.instructions.args.InsnArg;
|
||||||
|
import jadx.core.dex.instructions.args.Named;
|
||||||
|
import jadx.core.dex.instructions.args.RegisterArg;
|
||||||
|
import jadx.core.dex.nodes.ClassNode;
|
||||||
|
import jadx.tests.api.IntegrationTest;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static jadx.tests.api.utils.JadxMatchers.containsOne;
|
||||||
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
|
import static org.hamcrest.CoreMatchers.not;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
public class TestTernary3 extends IntegrationTest {
|
||||||
|
|
||||||
|
public static class TestCls {
|
||||||
|
|
||||||
|
public boolean isNameEquals(InsnArg arg) {
|
||||||
|
String n = getName(arg);
|
||||||
|
if (n == null || !(arg instanceof Named)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return n.equals(((Named) arg).getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getName(InsnArg arg) {
|
||||||
|
if (arg instanceof RegisterArg) {
|
||||||
|
return "r";
|
||||||
|
}
|
||||||
|
if (arg instanceof Named) {
|
||||||
|
return "n";
|
||||||
|
}
|
||||||
|
return arg.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void test() {
|
||||||
|
ClassNode cls = getClassNode(TestCls.class);
|
||||||
|
String code = cls.getCode().toString();
|
||||||
|
|
||||||
|
// TODO:
|
||||||
|
assertThat(code, containsOne("return (n == null || !(arg instanceof Named)) "
|
||||||
|
+ "? false : n.equals(((Named) arg).getName());"));
|
||||||
|
|
||||||
|
assertThat(code, not(containsString("if ((arg instanceof RegisterArg)) {")));
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user