Add initial transformer for reducing nesting in long if/else chains

pull/48/head
Graham 5 years ago
parent bf55b0d901
commit 556923559c
  1. 4
      deob-ast/src/main/java/dev/openrs2/deob/ast/AstDeobfuscator.java
  2. 58
      deob-ast/src/main/java/dev/openrs2/deob/ast/transform/IfElseTransformer.java
  3. 72
      deob-ast/src/main/java/dev/openrs2/deob/ast/visitor/NegateExprVisitor.java

@ -14,12 +14,14 @@ import com.github.javaparser.utils.SourceRoot;
import com.google.common.collect.ImmutableList;
import dev.openrs2.deob.ast.transform.AddSubTransformer;
import dev.openrs2.deob.ast.transform.ComplementTransformer;
import dev.openrs2.deob.ast.transform.IfElseTransformer;
import dev.openrs2.deob.ast.transform.Transformer;
public final class AstDeobfuscator {
private static final ImmutableList<Transformer> TRANSFORMERS = ImmutableList.of(
new AddSubTransformer(),
new ComplementTransformer()
new ComplementTransformer(),
new IfElseTransformer()
);
public static void main(String[] args) {

@ -0,0 +1,58 @@
package dev.openrs2.deob.ast.transform;
import com.github.javaparser.ast.CompilationUnit;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.stmt.IfStmt;
import com.github.javaparser.ast.stmt.Statement;
import dev.openrs2.deob.ast.visitor.NegateExprVisitor;
public final class IfElseTransformer extends Transformer {
private static boolean isIf(Statement stmt) {
if (stmt.isIfStmt()) {
return true;
} else if (stmt.isBlockStmt()) {
NodeList<Statement> stmts = stmt.asBlockStmt().getStatements();
return stmts.size() == 1 && stmts.get(0).isIfStmt();
} else {
return false;
}
}
private static Statement getIf(Statement stmt) {
if (stmt.isIfStmt()) {
return stmt;
} else if (stmt.isBlockStmt()) {
NodeList<Statement> stmts = stmt.asBlockStmt().getStatements();
if (stmts.size() == 1) {
Statement head = stmts.get(0);
if (head.isIfStmt()) {
return head;
}
}
}
throw new IllegalArgumentException();
}
@Override
public void transform(CompilationUnit unit) {
unit.findAll(IfStmt.class).forEach(stmt -> {
stmt.getElseStmt().ifPresent(elseStmt -> {
var thenStmt = stmt.getThenStmt();
if (isIf(thenStmt) && !isIf(elseStmt)) {
stmt.setCondition(stmt.getCondition().accept(new NegateExprVisitor(), null));
stmt.setThenStmt(elseStmt);
stmt.setElseStmt(thenStmt);
}
});
});
unit.findAll(IfStmt.class).forEach(stmt -> {
stmt.getElseStmt().ifPresent(elseStmt -> {
if (isIf(elseStmt)) {
stmt.setElseStmt(getIf(elseStmt));
}
});
});
}
}

@ -0,0 +1,72 @@
package dev.openrs2.deob.ast.visitor;
import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.NodeList;
import com.github.javaparser.ast.expr.BinaryExpr;
import com.github.javaparser.ast.expr.BooleanLiteralExpr;
import com.github.javaparser.ast.expr.EnclosedExpr;
import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.UnaryExpr;
import com.github.javaparser.ast.visitor.GenericVisitorWithDefaults;
// TODO(gpe): need to be careful about operator precedence/EnclosedExpr
public final class NegateExprVisitor extends GenericVisitorWithDefaults<Expression, Void> {
@Override
public Expression defaultAction(Node n, Void arg) {
if (!(n instanceof Expression)) {
throw new IllegalArgumentException();
}
return new UnaryExpr((Expression) n, UnaryExpr.Operator.LOGICAL_COMPLEMENT);
}
@Override
public Expression defaultAction(NodeList n, Void arg) {
throw new IllegalArgumentException();
}
@Override
public Expression visit(BinaryExpr n, Void arg) {
var left = n.getLeft();
var right = n.getRight();
switch (n.getOperator()) {
case EQUALS:
return new BinaryExpr(left, right, BinaryExpr.Operator.NOT_EQUALS);
case NOT_EQUALS:
return new BinaryExpr(left, right, BinaryExpr.Operator.EQUALS);
case GREATER:
return new BinaryExpr(left, right, BinaryExpr.Operator.LESS_EQUALS);
case GREATER_EQUALS:
return new BinaryExpr(left, right, BinaryExpr.Operator.LESS);
case LESS:
return new BinaryExpr(left, right, BinaryExpr.Operator.GREATER_EQUALS);
case LESS_EQUALS:
return new BinaryExpr(left, right, BinaryExpr.Operator.GREATER);
case AND:
return new BinaryExpr(left.accept(this, arg), right.accept(this, arg), BinaryExpr.Operator.OR);
case OR:
return new BinaryExpr(left.accept(this, arg), right.accept(this, arg), BinaryExpr.Operator.AND);
default:
return defaultAction(n, arg);
}
}
@Override
public Expression visit(BooleanLiteralExpr n, Void arg) {
return new BooleanLiteralExpr(!n.getValue());
}
@Override
public Expression visit(EnclosedExpr n, Void arg) {
return n.getInner().accept(this, arg);
}
@Override
public Expression visit(UnaryExpr n, Void arg) {
switch (n.getOperator()) {
case LOGICAL_COMPLEMENT:
return n.getExpression();
default:
return defaultAction(n, arg);
}
}
}
Loading…
Cancel
Save