mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-26 16:50:46 +00:00
Simplify nonif expressions while deobfuscation too
Regexp deobfuscation. Implicit coercion handling. #1145 double not (!!) fix
This commit is contained in:
@@ -17,15 +17,30 @@
|
||||
package com.jpexs.decompiler.graph;
|
||||
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.FloatValueAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.IntegerValueAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.NameValuePair;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.NewArrayAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.NewObjectAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.ThisAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.UndefinedAVM2Item;
|
||||
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.ecma.ArrayType;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.ecma.ObjectType;
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter;
|
||||
import com.jpexs.decompiler.flash.helpers.hilight.HighlightData;
|
||||
import com.jpexs.decompiler.graph.model.BinaryOp;
|
||||
import com.jpexs.decompiler.graph.model.FalseItem;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.decompiler.graph.model.NotItem;
|
||||
import com.jpexs.decompiler.graph.model.TrueItem;
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
@@ -90,6 +105,92 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return lineStartItem;
|
||||
}
|
||||
|
||||
protected static GraphTargetItem valToItem(Object r) {
|
||||
if (r == null) {
|
||||
return null;
|
||||
}
|
||||
if (r instanceof Boolean) {
|
||||
if ((Boolean) r) {
|
||||
return new TrueItem(null, null);
|
||||
} else {
|
||||
return new FalseItem(null, null);
|
||||
}
|
||||
}
|
||||
if (r instanceof String) {
|
||||
return new StringAVM2Item(null, null, (String) r);
|
||||
}
|
||||
if (r instanceof Long) {
|
||||
return new IntegerValueAVM2Item(null, null, (Long) r);
|
||||
}
|
||||
if (r instanceof Integer) {
|
||||
return new IntegerValueAVM2Item(null, null, (long) (int) (Integer) r);
|
||||
}
|
||||
|
||||
if (r instanceof Double) {
|
||||
return new FloatValueAVM2Item(null, null, (Double) r);
|
||||
}
|
||||
if (r instanceof Null) {
|
||||
return new NullAVM2Item(null, null);
|
||||
}
|
||||
if (r instanceof Undefined) {
|
||||
return new UndefinedAVM2Item(null, null);
|
||||
}
|
||||
if (r instanceof ArrayType) {
|
||||
List<GraphTargetItem> vals = new ArrayList<>();
|
||||
ArrayType at = (ArrayType) r;
|
||||
for (Object v : at.values) {
|
||||
vals.add(valToItem(v));
|
||||
}
|
||||
return new NewArrayAVM2Item(null, null, vals);
|
||||
}
|
||||
if (r instanceof ObjectType) {
|
||||
List<NameValuePair> props = new ArrayList<>();
|
||||
ObjectType ot = (ObjectType) r;
|
||||
for (String k : ot.getAttributeNames()) {
|
||||
props.add(new NameValuePair(valToItem(k), valToItem(ot.getAttribute(k))));
|
||||
}
|
||||
return new NewObjectAVM2Item(null, null, props);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static GraphTargetItem simplifySomething(GraphTargetItem it, String implicitCoerce) {
|
||||
if ((it instanceof SimpleValue) && implicitCoerce.isEmpty()) {
|
||||
if (((SimpleValue) it).isSimpleValue()) {
|
||||
return it;
|
||||
}
|
||||
}
|
||||
|
||||
if (!it.isCompileTime() && !(!implicitCoerce.isEmpty() && it.isConvertedCompileTime(new HashSet<>()))) {
|
||||
return it;
|
||||
}
|
||||
Object r = it.getResult();
|
||||
switch (implicitCoerce) {
|
||||
case "String":
|
||||
r = EcmaScript.toString(r);
|
||||
break;
|
||||
case "Number":
|
||||
r = EcmaScript.toNumber(r);
|
||||
break;
|
||||
case "int":
|
||||
r = EcmaScript.toInt32(r);
|
||||
break;
|
||||
case "Boolean":
|
||||
r = EcmaScript.toBoolean(r);
|
||||
break;
|
||||
}
|
||||
|
||||
GraphTargetItem it2 = valToItem(r);
|
||||
if (it2 == null) {
|
||||
return it;
|
||||
}
|
||||
return it2;
|
||||
}
|
||||
|
||||
public GraphTargetItem simplify(String implicitCoerce) {
|
||||
return simplifySomething(this, implicitCoerce);
|
||||
}
|
||||
|
||||
public int getLine() {
|
||||
if (src != null) {
|
||||
return src.getLine();
|
||||
@@ -174,7 +275,7 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
}
|
||||
|
||||
writer.startOffset(src, getLineStartItem(), getPos(), srcData);
|
||||
appendTo(writer, localData);
|
||||
appendTry(writer, localData);
|
||||
if (needsSemicolon()) {
|
||||
writer.appendNoHilight(";");
|
||||
}
|
||||
@@ -191,19 +292,52 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return getClass().getName();
|
||||
}
|
||||
|
||||
public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
public GraphTextWriter toStringBoolean(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData, "Boolean");
|
||||
}
|
||||
|
||||
public GraphTextWriter toStringString(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData, "String");
|
||||
}
|
||||
|
||||
public GraphTextWriter toStringInt(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData, "int");
|
||||
}
|
||||
|
||||
public GraphTextWriter toStringNumber(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData, "Number");
|
||||
}
|
||||
|
||||
public GraphTextWriter toString(GraphTextWriter writer, LocalData localData, String implicitCoerce) throws InterruptedException {
|
||||
if (Thread.currentThread().isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
|
||||
writer.startOffset(src, getLineStartItem(), getPos(), srcData);
|
||||
appendTo(writer, localData);
|
||||
appendTry(writer, localData, implicitCoerce);
|
||||
writer.endOffset();
|
||||
return writer;
|
||||
}
|
||||
|
||||
public GraphTextWriter toString(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return toString(writer, localData, "");
|
||||
}
|
||||
|
||||
public abstract GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException;
|
||||
|
||||
public GraphTextWriter appendTry(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
return appendTry(writer, localData, "");
|
||||
}
|
||||
|
||||
public GraphTextWriter appendTry(GraphTextWriter writer, LocalData localData, String implicitCoerce) throws InterruptedException {
|
||||
GraphTargetItem t = this;
|
||||
if (!implicitCoerce.isEmpty() && Configuration.autoDeobfuscate.get()) {
|
||||
t = t.simplify(implicitCoerce);
|
||||
}
|
||||
return t.appendTo(writer, localData);
|
||||
|
||||
}
|
||||
|
||||
public String toString(LocalData localData) throws InterruptedException {
|
||||
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false);
|
||||
toString(writer, localData);
|
||||
@@ -224,6 +358,10 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isConvertedCompileTime(Set<GraphTargetItem> dependencies) {
|
||||
return isCompileTime();
|
||||
}
|
||||
|
||||
public boolean hasSideEffect() {
|
||||
return false;
|
||||
}
|
||||
@@ -274,7 +412,7 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
|
||||
|
||||
public GraphTextWriter toStringNL(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
writer.startOffset(src, getLineStartItem(), getPos(), srcData);
|
||||
appendTo(writer, localData);
|
||||
appendTry(writer, localData);
|
||||
if (needsNewLine()) {
|
||||
writer.newLine();
|
||||
}
|
||||
|
||||
@@ -31,6 +31,12 @@ public class TranslateStack extends Stack<GraphTargetItem> {
|
||||
|
||||
private final String path;
|
||||
|
||||
public void simplify() {
|
||||
for (int i = 0; i < size(); i++) {
|
||||
set(i, get(i).simplify(""));
|
||||
}
|
||||
}
|
||||
|
||||
public TranslateStack(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ public class AndItem extends BinaryOpItem {
|
||||
}
|
||||
|
||||
public AndItem(GraphSourceItem src, GraphSourceItem lineStartIns, GraphTargetItem leftSide, GraphTargetItem rightSide) {
|
||||
super(src, lineStartIns, PRECEDENCE_LOGICALAND, leftSide, rightSide, "&&");
|
||||
super(src, lineStartIns, PRECEDENCE_LOGICALAND, leftSide, rightSide, "&&", "Boolean", "Boolean");
|
||||
this.leftSide = leftSide;
|
||||
this.rightSide = rightSide;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,9 @@ public abstract class BinaryOpItem extends GraphTargetItem implements BinaryOp {
|
||||
|
||||
protected final String operator;
|
||||
|
||||
protected String coerceLeft;
|
||||
protected String coerceRight;
|
||||
|
||||
@Override
|
||||
public GraphPart getFirstPart() {
|
||||
GraphPart fp = leftSide.getFirstPart();
|
||||
@@ -47,11 +50,21 @@ public abstract class BinaryOpItem extends GraphTargetItem implements BinaryOp {
|
||||
return fp;
|
||||
}
|
||||
|
||||
public BinaryOpItem(GraphSourceItem instruction, GraphSourceItem lineStartItem, int precedence, GraphTargetItem leftSide, GraphTargetItem rightSide, String operator) {
|
||||
public BinaryOpItem(GraphSourceItem instruction, GraphSourceItem lineStartItem, int precedence, GraphTargetItem leftSide, GraphTargetItem rightSide, String operator, String coerceLeft, String coerceRight) {
|
||||
super(instruction, lineStartItem, precedence);
|
||||
this.leftSide = leftSide;
|
||||
this.rightSide = rightSide;
|
||||
this.operator = operator;
|
||||
this.coerceLeft = coerceLeft;
|
||||
this.coerceRight = coerceRight;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTargetItem simplify(String implicitCoerce) {
|
||||
BinaryOpItem r = (BinaryOpItem) clone();
|
||||
r.leftSide = r.leftSide.simplify(coerceLeft);
|
||||
r.rightSide = r.rightSide.simplify(coerceRight);
|
||||
return simplifySomething(r, implicitCoerce);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -98,7 +111,7 @@ public abstract class BinaryOpItem extends GraphTargetItem implements BinaryOp {
|
||||
return false;
|
||||
}
|
||||
dependencies.add(rightSide);
|
||||
return leftSide.isCompileTime(dependencies) && rightSide.isCompileTime(dependencies);
|
||||
return leftSide.isConvertedCompileTime(dependencies) && rightSide.isConvertedCompileTime(dependencies);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -86,7 +86,12 @@ public class DoWhileItem extends LoopItem implements Block {
|
||||
if (i != 0) {
|
||||
writer.append(", ");
|
||||
}
|
||||
expression.get(i).toString(writer, localData);
|
||||
if (i == expression.size() - 1) {
|
||||
expression.get(i).toStringBoolean(writer, localData);
|
||||
} else {
|
||||
expression.get(i).toString(writer, localData);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
writer.append(");").newLine();
|
||||
|
||||
@@ -51,10 +51,10 @@ public class DuplicateItem extends GraphTargetItem implements SimpleValue {
|
||||
@Override
|
||||
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
if (((value instanceof SimpleValue) && (((SimpleValue) value).isSimpleValue())) || !Configuration.displayDupInstructions.get()) {
|
||||
return value.appendTo(writer, localData);
|
||||
return value.appendTry(writer, localData);
|
||||
}
|
||||
writer.append("§§dup(");
|
||||
value.appendTo(writer, localData);
|
||||
value.appendTry(writer, localData);
|
||||
return writer.append(")");
|
||||
}
|
||||
|
||||
@@ -102,9 +102,14 @@ public class DuplicateItem extends GraphTargetItem implements SimpleValue {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTargetItem simplify(String implicitCoerce) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTargetItem returnType() {
|
||||
return TypeItem.UNBOUNDED;
|
||||
return value.returnType();
|
||||
}
|
||||
|
||||
/*@Override
|
||||
|
||||
@@ -95,7 +95,7 @@ public class ForItem extends LoopItem implements Block {
|
||||
p++;
|
||||
}
|
||||
writer.append("; ");
|
||||
expression.toString(writer, localData);
|
||||
expression.toStringBoolean(writer, localData);
|
||||
writer.append("; ");
|
||||
p = 0;
|
||||
for (int i = 0; i < finalCommands.size(); i++) {
|
||||
|
||||
@@ -89,7 +89,7 @@ public class IfItem extends GraphTargetItem implements Block {
|
||||
writer.append(" ");
|
||||
}
|
||||
writer.append("(");
|
||||
expr.toString(writer, localData);
|
||||
expr.toStringBoolean(writer, localData);
|
||||
writer.append(")");
|
||||
appendBlock(expr, writer, localData, ifBranch);
|
||||
if (elseBranch.size() > 0) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package com.jpexs.decompiler.graph.model;
|
||||
import com.jpexs.decompiler.flash.SourceGeneratorLocalData;
|
||||
import com.jpexs.decompiler.flash.action.model.operations.Inverted;
|
||||
import com.jpexs.decompiler.flash.ecma.EcmaScript;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.CompilationException;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
@@ -34,7 +35,7 @@ import java.util.Set;
|
||||
public class NotItem extends UnaryOpItem implements LogicalOpItem, Inverted {
|
||||
|
||||
public NotItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, GraphTargetItem value) {
|
||||
super(instruction, lineStartIns, PRECEDENCE_UNARY, value, "!");
|
||||
super(instruction, lineStartIns, PRECEDENCE_UNARY, value, "!", "Boolean");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -79,8 +80,30 @@ public class NotItem extends UnaryOpItem implements LogicalOpItem, Inverted {
|
||||
return TypeItem.BOOLEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTextWriter toStringBoolean(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
//Skip explicit conversion to boolean, it is not needed, it is done implicitly
|
||||
if (value instanceof NotItem) {
|
||||
return value.value.toStringBoolean(writer, localData);
|
||||
}
|
||||
return super.toStringBoolean(writer, localData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTargetItem invert(GraphSourceItem src) {
|
||||
if (true) {
|
||||
return value;
|
||||
}
|
||||
//if this is already !!val, convert to !val
|
||||
if (value instanceof NotItem) {
|
||||
return value;
|
||||
}
|
||||
//If it is not a boolean, put !! there for toBoolean conversion
|
||||
if (!TypeItem.BOOLEAN.equals(value.returnType()) && !(value instanceof DuplicateItem)) {
|
||||
return new NotItem(null, null, this);
|
||||
}
|
||||
|
||||
//can be inverted
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import java.util.List;
|
||||
public class OrItem extends BinaryOpItem {
|
||||
|
||||
public OrItem(GraphSourceItem src, GraphSourceItem lineStartIns, GraphTargetItem leftSide, GraphTargetItem rightSide) {
|
||||
super(src, lineStartIns, PRECEDENCE_LOGICALOR, leftSide, rightSide, "||");
|
||||
super(src, lineStartIns, PRECEDENCE_LOGICALOR, leftSide, rightSide, "||", "Boolean", "Boolean");
|
||||
this.leftSide = leftSide;
|
||||
this.rightSide = rightSide;
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ public class PushItem extends GraphTargetItem {
|
||||
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
//Logger.getLogger(PushItem.class.getName()).log(Level.WARNING, "Push item left in the source code");
|
||||
writer.append("§§push(");
|
||||
value.appendTo(writer, localData);
|
||||
value.appendTry(writer, localData);
|
||||
writer.append(")");
|
||||
return writer;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.graph.model;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.ThisAVM2Item;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItemPos;
|
||||
@@ -30,10 +31,19 @@ import java.util.Set;
|
||||
public abstract class UnaryOpItem extends GraphTargetItem implements UnaryOp {
|
||||
|
||||
public String operator;
|
||||
protected String coerce;
|
||||
|
||||
public UnaryOpItem(GraphSourceItem instruction, GraphSourceItem lineStartItem, int precedence, GraphTargetItem value, String operator) {
|
||||
public UnaryOpItem(GraphSourceItem instruction, GraphSourceItem lineStartItem, int precedence, GraphTargetItem value, String operator, String coerce) {
|
||||
super(instruction, lineStartItem, precedence, value);
|
||||
this.operator = operator;
|
||||
this.coerce = coerce;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GraphTargetItem simplify(String implicitCoerce) {
|
||||
GraphTargetItem r = clone();
|
||||
r.value = r.value.simplify(coerce);
|
||||
return simplifySomething(r, implicitCoerce);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -59,7 +69,7 @@ public abstract class UnaryOpItem extends GraphTargetItem implements UnaryOp {
|
||||
return false;
|
||||
}
|
||||
dependencies.add(value);
|
||||
return value.isCompileTime(dependencies);
|
||||
return value.isConvertedCompileTime(dependencies);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -77,7 +77,12 @@ public class WhileItem extends LoopItem implements Block {
|
||||
if (i != 0) {
|
||||
writer.append(", ");
|
||||
}
|
||||
expression.get(i).toString(writer, localData);
|
||||
if (i == expression.size() - 1) {
|
||||
expression.get(i).toStringBoolean(writer, localData);
|
||||
} else {
|
||||
expression.get(i).toString(writer, localData);
|
||||
}
|
||||
|
||||
}
|
||||
writer.append(")");
|
||||
appendBlock(expression.get(expression.size() - 1), writer, localData, commands);
|
||||
|
||||
Reference in New Issue
Block a user