Commit d748e004 authored by Skylot's avatar Skylot

core: fix missing parenthesis in conditions

parent 380b73d1
...@@ -16,6 +16,8 @@ import jadx.core.utils.exceptions.CodegenException; ...@@ -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; ...@@ -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 { ...@@ -75,19 +114,16 @@ public class ConditionGen extends InsnGen {
} }
if (op == IfOp.EQ) { if (op == IfOp.EQ) {
// == true // == true
if (stack.getStack().size() == 1) {
addArg(code, firstArg, false); 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 { ...@@ -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 { ...@@ -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 { ...@@ -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) {
......
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)) {")));
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment