Fixed #1842 AS1/2 Better handling obfuscated code, for..in

This commit is contained in:
Jindra Petřík
2023-01-22 22:15:04 +01:00
parent b0a9b977d0
commit 051087e9ad
24 changed files with 335 additions and 72 deletions
@@ -37,6 +37,7 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.MethodInfo;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.ecma.Null;
import com.jpexs.decompiler.graph.Graph;
import com.jpexs.decompiler.graph.GraphPart;
import com.jpexs.decompiler.graph.GraphSource;
import com.jpexs.decompiler.graph.GraphSourceItem;
@@ -290,7 +291,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple {
}
@Override
public List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
public List<GraphTargetItem> translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@@ -298,7 +298,7 @@ public class AVM2DeobfuscatorRegistersOld extends AVM2DeobfuscatorSimpleOld {
}
@Override
public List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
public List<GraphTargetItem> translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
}
@@ -2427,7 +2427,7 @@ public class AVM2Graph extends Graph {
}
}
public static void makeAllCommands(List<GraphTargetItem> commands, TranslateStack stack) {
public void makeAllCommands(List<GraphTargetItem> commands, TranslateStack stack) {
for (int i = 0; i < stack.size(); i++) {
//These are often obfuscated, so ignore them
if (stack.get(i) instanceof NewFunctionAVM2Item) {
@@ -2435,7 +2435,7 @@ public class AVM2Graph extends Graph {
i--;
}
}
Graph.makeAllCommands(commands, stack);
super.makeAllCommands(commands, stack);
}
@Override
@@ -24,6 +24,7 @@ import com.jpexs.decompiler.flash.abc.avm2.ConvertOutput;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.Graph;
import com.jpexs.decompiler.graph.GraphPart;
import com.jpexs.decompiler.graph.GraphSource;
import com.jpexs.decompiler.graph.GraphSourceItem;
@@ -115,7 +116,7 @@ public class AVM2GraphSource extends GraphSource {
}
@Override
public List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
public List<GraphTargetItem> translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException {
List<GraphTargetItem> ret = new ArrayList<>();
ScopeStack newstack = ((AVM2LocalData) localData).scopeStack;
Reference<GraphSourceItem> lineStartItem = new Reference<>(localData.lineStartInstruction);
@@ -1010,7 +1010,7 @@ public abstract class Action implements GraphSourceItem {
return variables2;
}
public static List<GraphTargetItem> actionsPartToTree(Set<GraphPart> switchParts, SecondPassData secondPassData, boolean insideDoInitAction, Reference<GraphSourceItem> fi, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, TranslateStack stack, List<Action> actions, int start, int end, int version, int staticOperation, String path, String charset) throws InterruptedException, GraphPartChangeException {
public static List<GraphTargetItem> actionsPartToTree(ActionGraph graph, Set<GraphPart> switchParts, SecondPassData secondPassData, boolean insideDoInitAction, Reference<GraphSourceItem> fi, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, TranslateStack stack, List<Action> actions, int start, int end, int version, int staticOperation, String path, String charset) throws InterruptedException, GraphPartChangeException {
if (start < actions.size() && (end > 0) && (start > 0)) {
logger.log(Level.FINE, "Entering {0}-{1}{2}", new Object[]{start, end, actions.size() > 0 ? (" (" + actions.get(start).toString() + " - " + actions.get(end == actions.size() ? end - 1 : end) + ")") : ""});
}
@@ -1135,7 +1135,7 @@ public abstract class Action implements GraphSourceItem {
if (((action instanceof ActionSetTarget) || (action instanceof ActionSetTarget2)) && (!stack.isEmpty())) {
GraphTargetItem lastItem = output.remove(output.size() - 1);
Graph.makeAllCommands(output, stack);
graph.makeAllCommands(output, stack);
output.add(lastItem);
}
@@ -22,13 +22,16 @@ import com.jpexs.decompiler.flash.SWF;
import static com.jpexs.decompiler.flash.action.Action.adr2ip;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.model.EnumerateActionItem;
import com.jpexs.decompiler.flash.action.model.EnumeratedValueActionItem;
import com.jpexs.decompiler.flash.action.model.FunctionActionItem;
import com.jpexs.decompiler.flash.action.model.GetPropertyActionItem;
import com.jpexs.decompiler.flash.action.model.SetTarget2ActionItem;
import com.jpexs.decompiler.flash.action.model.SetTargetActionItem;
import com.jpexs.decompiler.flash.action.model.SetTypeActionItem;
import com.jpexs.decompiler.flash.action.model.SetVariableActionItem;
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.model.TemporaryRegisterMark;
import com.jpexs.decompiler.flash.action.model.clauses.ForInActionItem;
import com.jpexs.decompiler.flash.action.model.clauses.TellTargetActionItem;
import com.jpexs.decompiler.flash.action.model.operations.NeqActionItem;
@@ -93,7 +96,7 @@ public class ActionGraph extends Graph {
this.insideDoInitAction = insideDoInitAction;
this.insideFunction = insideFunction;
}
@Override
public ActionGraphSource getGraphCode() {
return (ActionGraphSource) code;
@@ -121,7 +124,7 @@ public class ActionGraph extends Graph {
for (ActionList al : outs) {
subgraphs.put("loc" + Helper.formatAddress(code.pos2adr(ip)) + ": function " + functionName,
new ActionGraph("", false, false, al, new HashMap<>(), new HashMap<>(), new HashMap<>(), SWF.DEFAULT_VERSION, ((ActionGraphSource)getGraphCode()).getCharset())
new ActionGraph("", false, false, al, new HashMap<>(), new HashMap<>(), new HashMap<>(), SWF.DEFAULT_VERSION, ((ActionGraphSource) getGraphCode()).getCharset())
);
}
}
@@ -353,29 +356,65 @@ public class ActionGraph extends Graph {
checkedLoop = null;
}
}
if (checkedBody != null && (!checkedBody.isEmpty()) && (checkedBody.get(0) instanceof SetTypeActionItem)) {
SetTypeActionItem sti = (SetTypeActionItem) checkedBody.get(0);
if (checkedCondition instanceof NeqActionItem) {
NeqActionItem ne = (NeqActionItem) checkedCondition;
if (ne.rightSide instanceof DirectValueActionItem) {
DirectValueActionItem dv = (DirectValueActionItem) ne.rightSide;
if (dv.value == Null.INSTANCE) {
GraphTargetItem en = list.get(t - 1);
if (en instanceof EnumerateActionItem) {
EnumerateActionItem eti = (EnumerateActionItem) en;
list.remove(t);
checkedBody.remove(0);
if (checkedLoop == null) {
checkedLoop = new Loop(localData.loops.size(), null, null);
checkedBody.add(new BreakItem(null, null, checkedLoop.id));
if (checkedCondition instanceof NeqActionItem) {
NeqActionItem ne = (NeqActionItem) checkedCondition;
if (ne.rightSide instanceof DirectValueActionItem) {
DirectValueActionItem dv = (DirectValueActionItem) ne.rightSide;
if (dv.value == Null.INSTANCE) {
GraphTargetItem en = list.get(t - 1);
if (en instanceof EnumerateActionItem) {
EnumerateActionItem eti = (EnumerateActionItem) en;
if (checkedCondition instanceof NeqActionItem) {
NeqActionItem neq = (NeqActionItem) checkedCondition;
if (neq.leftSide instanceof StoreRegisterActionItem) {
if (checkedBody != null && (!checkedBody.isEmpty()) && (checkedBody.get(0) instanceof SetTypeActionItem)) {
SetTypeActionItem sti = (SetTypeActionItem) checkedBody.get(0);
if ((sti.getValue() instanceof DirectValueActionItem) && (((DirectValueActionItem) sti.getValue()).value instanceof RegisterNumber)) {
if ((neq.rightSide instanceof DirectValueActionItem) && (((DirectValueActionItem) neq.rightSide).value instanceof Null)) {
if (neq.leftSide.value instanceof EnumeratedValueActionItem) {
if (((StoreRegisterActionItem) neq.leftSide).register.number == ((RegisterNumber) (((DirectValueActionItem) sti.getValue()).value)).number) {
list.remove(t);
checkedBody.remove(0);
if (checkedLoop == null) {
checkedLoop = new Loop(localData.loops.size(), null, null);
checkedBody.add(new BreakItem(null, null, checkedLoop.id));
}
sti.setValue(new DirectValueActionItem(Null.INSTANCE));
list.add(t, new ForInActionItem(null, null, checkedLoop, (GraphTargetItem) sti, eti.object, checkedBody));
//sti.getObject()
list.remove(t - 1);
t--;
continue;
}
}
}
}
}
if (checkedBody != null) {
list.remove(t);
if (checkedLoop == null) {
checkedLoop = new Loop(localData.loops.size(), null, null);
checkedBody.add(new BreakItem(null, null, checkedLoop.id));
}
list.remove(t - 1);
t--;
if (eti.object instanceof SetTypeActionItem) {
list.add(t++, eti.object);
eti.object = ((SetTypeActionItem)eti.object).getObject();
}
list.add(t, new ForInActionItem(null, null, checkedLoop, (GraphTargetItem) neq.leftSide, eti.object, checkedBody));
if (t + 1 < list.size()) {
if (list.get(t + 1) instanceof EnumeratedValueActionItem) {
list.remove(t + 1);
}
}
}
}
sti.setValue(new DirectValueActionItem(Null.INSTANCE));
list.add(t, new ForInActionItem(null, null, checkedLoop, (GraphTargetItem) sti/*sti.getObject()*/, eti.object, checkedBody));
list.remove(t - 1);
t--;
}
}
}
}
}
@@ -386,6 +425,44 @@ public class ActionGraph extends Graph {
}
public void makeAllCommands(List<GraphTargetItem> commands, TranslateStack stack) {
super.makeAllCommands(commands, stack);
//ags.getVariables()
ActionGraphSource ags = (ActionGraphSource) code;
for (String varName : ags.getVariables().keySet()) {
if (varName.matches("^__register.*")) {
GraphTargetItem varValue = ags.getVariables().get(varName);
if (varValue instanceof TemporaryRegister) {
TemporaryRegister tempReg = (TemporaryRegister) varValue;
if (!tempReg.used) {
if (varValue.value instanceof SetTypeActionItem) {
SetTypeActionItem st = (SetTypeActionItem) varValue.value;
for (int i = 0; i < commands.size(); i++) {
if (commands.get(i) instanceof TemporaryRegisterMark) {
TemporaryRegisterMark trm = (TemporaryRegisterMark) commands.get(i);
if (st.getValue() instanceof StoreRegisterActionItem) {
StoreRegisterActionItem sr = (StoreRegisterActionItem) st.getValue();
if (sr.register.number == tempReg.getRegId()) {
sr.temporary = false;
}
}
if (trm.tempReg == tempReg) {
commands.set(i, (GraphTargetItem) st);
ags.getVariables().put(varName, null);
break;
}
}
}
}
}
//System.err.println(varValue.value.getClass().getSimpleName());
}
}
}
}
@Override
public List<GraphTargetItem> translate(BaseLocalData localData, int staticOperation, String path) throws InterruptedException {
List<GraphTargetItem> ret = super.translate(localData, staticOperation, path);
@@ -18,6 +18,7 @@ package com.jpexs.decompiler.flash.action;
import com.jpexs.decompiler.flash.BaseLocalData;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.graph.Graph;
import com.jpexs.decompiler.graph.GraphPart;
import com.jpexs.decompiler.graph.GraphPartChangeException;
import com.jpexs.decompiler.graph.GraphSource;
@@ -109,10 +110,10 @@ public class ActionGraphSource extends GraphSource {
}
@Override
public List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException {
public List<GraphTargetItem> translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException {
Reference<GraphSourceItem> fi = new Reference<>(localData.lineStartInstruction);
List<GraphTargetItem> r = Action.actionsPartToTree(localData.allSwitchParts, localData.secondPassData, this.insideDoInitAction, fi, registerNames, variables, functions, stack, actions, start, end, version, staticOperation, path, charset);
List<GraphTargetItem> r = Action.actionsPartToTree((ActionGraph)graph, localData.allSwitchParts, localData.secondPassData, this.insideDoInitAction, fi, registerNames, variables, functions, stack, actions, start, end, version, staticOperation, path, charset);
localData.lineStartInstruction = fi.getVal();
return r;
}
@@ -279,7 +279,7 @@ public class ActionScript2ClassDetector {
}
private boolean checkClassContent(List<GraphTargetItem> parts, HashMap<String, GraphTargetItem> variables, int partsPos, int commandsStartPos, int commandsEndPos, List<GraphTargetItem> commands, List<String> classNamePath, String scriptPath) {
try {
GraphTargetItem extendsOp = null;
@@ -299,29 +299,7 @@ public class ActionScript2ClassDetector {
StoreRegisterActionItem sr = (StoreRegisterActionItem) item;
definedRegisters.add(sr.register.number);
}
}
/*
Hack:
When register is not used after setting, then FFDec discards its value,
but the value is crucial as there is setmember, atc.
This will bypass the situation.
This happens when there are no methods/vars, constructor only.
*/
int numr = 0;
for (String s : variables.keySet()) {
Matcher m = regPattern.matcher(s);
if (m.matches()) {
if (variables.get(s) instanceof TemporaryRegister) {
int regId = Integer.parseInt(m.group(1));
if (!definedRegisters.contains(regId)) {
parts.add(partsPos + numr, variables.get(s).value);
numr++;
}
}
}
}
}
if (parts.size() > partsPos) {
item = parts.get(partsPos);
@@ -31,6 +31,8 @@ import java.util.Objects;
public class TemporaryRegister extends ActionItem {
private final int regId;
public boolean used = false;
public TemporaryRegister(int regId, GraphTargetItem value) {
super(value.getSrc(), value.getLineStartItem(), value.getPrecedence(), value);
@@ -0,0 +1,60 @@
/*
* Copyright (C) 2010-2022 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.action.model;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.model.LocalData;
/**
*
* @author JPEXS
*/
public class TemporaryRegisterMark extends ActionItem {
public TemporaryRegister tempReg;
public TemporaryRegisterMark(TemporaryRegister tempReg) {
this.tempReg = tempReg;
}
@Override
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
return writer;
}
@Override
public boolean needsNewLine() {
return false;
}
@Override
public boolean needsSemicolon() {
return false;
}
@Override
public boolean hasReturnValue() {
return false;
}
@Override
public boolean isEmpty() {
return true;
}
}
@@ -128,7 +128,13 @@ public class ForInActionItem extends LoopActionItem implements Block {
}
writer.append(" in ");
if (enumVariable.getPrecedence() > PRECEDENCE_PRIMARY) {
writer.append("(");
}
enumVariable.toString(writer, localData);
if (enumVariable.getPrecedence() > PRECEDENCE_PRIMARY) {
writer.append(")");
}
writer.append(")").startBlock();
for (GraphTargetItem ti : commands) {
ti.toStringSemicoloned(writer, localData).newLine();
@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.action.LocalDataArea;
import com.jpexs.decompiler.flash.action.model.DirectValueActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.model.TemporaryRegisterMark;
import com.jpexs.decompiler.flash.action.model.UnresolvedConstantActionItem;
import com.jpexs.decompiler.flash.action.parser.ActionParseException;
import com.jpexs.decompiler.flash.action.parser.pcode.ASMParsedSymbol;
@@ -448,6 +449,16 @@ public class ActionPush extends Action {
}
}
if (dvt.computedRegValue instanceof TemporaryRegister) {
((TemporaryRegister)dvt.computedRegValue).used = true;
for(int i = 0; i < output.size(); i++) {
if(output.get(i) instanceof TemporaryRegisterMark) {
TemporaryRegisterMark trm = (TemporaryRegisterMark)output.get(i);
if(trm.tempReg == dvt.computedRegValue) {
output.remove(i);
break;
}
}
}
stack.push(new TemporaryRegister(((RegisterNumber) o).number, ((TemporaryRegister) dvt.computedRegValue).value));
} else {
stack.push(dvt);
@@ -29,6 +29,7 @@ import com.jpexs.decompiler.flash.action.model.PostIncrementActionItem;
import com.jpexs.decompiler.flash.action.model.SetPropertyActionItem;
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.model.TemporaryRegisterMark;
import com.jpexs.decompiler.flash.action.model.operations.PreDecrementActionItem;
import com.jpexs.decompiler.flash.action.model.operations.PreIncrementActionItem;
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
@@ -164,7 +165,9 @@ public class ActionSetProperty extends Action {
sr.temporary = true;
((SetPropertyActionItem) ret).setValue(sr);
}
variables.put("__register" + sr.register.number, new TemporaryRegister(sr.register.number, ret));
TemporaryRegister tr = new TemporaryRegister(sr.register.number, ret);
variables.put("__register" + sr.register.number, tr);
output.add(new TemporaryRegisterMark(tr));
return;
}
}
@@ -30,6 +30,7 @@ import com.jpexs.decompiler.flash.action.model.PostIncrementActionItem;
import com.jpexs.decompiler.flash.action.model.SetVariableActionItem;
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.model.TemporaryRegisterMark;
import com.jpexs.decompiler.flash.action.model.operations.PreDecrementActionItem;
import com.jpexs.decompiler.flash.action.model.operations.PreIncrementActionItem;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
@@ -172,7 +173,9 @@ public class ActionSetVariable extends Action implements StoreTypeAction {
((SetVariableActionItem) ret).setValue(sr);
}
variables.put("__register" + sr.register.number, new TemporaryRegister(sr.register.number, ret));
TemporaryRegister tr = new TemporaryRegister(sr.register.number, ret);
variables.put("__register" + sr.register.number, tr);
output.add(new TemporaryRegisterMark(tr));
return;
}
}
@@ -28,6 +28,7 @@ import com.jpexs.decompiler.flash.action.model.PostIncrementActionItem;
import com.jpexs.decompiler.flash.action.model.SetMemberActionItem;
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.model.TemporaryRegisterMark;
import com.jpexs.decompiler.flash.action.model.operations.PreDecrementActionItem;
import com.jpexs.decompiler.flash.action.model.operations.PreIncrementActionItem;
import com.jpexs.decompiler.flash.types.annotations.SWFVersion;
@@ -156,7 +157,9 @@ public class ActionSetMember extends Action {
sr.temporary = true;
((SetMemberActionItem) ret).setValue(sr);
}
variables.put("__register" + sr.register.number, new TemporaryRegister(sr.register.number, ret));
TemporaryRegister tr = new TemporaryRegister(sr.register.number, ret);
variables.put("__register" + sr.register.number, tr);
output.add(new TemporaryRegisterMark(tr));
return;
}
}
@@ -161,7 +161,9 @@ public class ActionStoreRegister extends Action implements StoreTypeAction {
}
if ((value instanceof EnumeratedValueActionItem)) {
variables.put("__register" + registerNumber, new TemporaryRegister(registerNumber, new EnumerationAssignmentValueActionItem()));
//variables.put("__register" + registerNumber, new TemporaryRegister(registerNumber, new EnumerationAssignmentValueActionItem()));
//variables.put("__register" + registerNumber, null);
variables.remove("__register" + registerNumber);
}
StoreRegisterActionItem ret = new StoreRegisterActionItem(this, lineStartAction, rn, value, define);
if (value.getNotCoercedNoDup() instanceof CompoundableBinaryOp) {
@@ -1485,7 +1485,7 @@ public class Graph {
}
end = p.end;
int start = p.start;
ret.addAll(code.translatePart(part, localData, stack, start, end, staticOperation, path));
ret.addAll(code.translatePart(this, part, localData, stack, start, end, staticOperation, path));
}
return ret;
}
@@ -2039,6 +2039,7 @@ public class Graph {
}
protected List<GraphTargetItem> printGraph(List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, BaseLocalData localData, TranslateStack stack, Set<GraphPart> allParts, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<StopPartKind> stopPartKind, List<Loop> loops, List<ThrowState> throwStates, List<GraphTargetItem> ret, int staticOperation, String path, int recursionLevel) throws InterruptedException {
loopPrintGraph:while(true) {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
@@ -2273,7 +2274,7 @@ public class Graph {
do {
exHappened = false;
try {
output.addAll(code.translatePart(part, localData, stack, ipStart, part.end, staticOperation, path));
output.addAll(code.translatePart(this, part, localData, stack, ipStart, part.end, staticOperation, path));
} catch (GraphPartChangeException ex) { //Special case for ifFrameLoaded when it's over multiple parts
output.addAll(ex.getOutput());
for (GraphPart p : allParts) {
@@ -2282,7 +2283,8 @@ public class Graph {
currentRet.addAll(output);
//to check for stopparts,etc. we need to call printGraph again
part = p;
return printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, parent, part, stopPart, stopPartKind, loops, throwStates, ret, staticOperation, path, recursionLevel);
//return printGraph(foundGotos, partCodes, partCodePos, visited, localData, stack, allParts, parent, part, stopPart, stopPartKind, loops, throwStates, ret, staticOperation, path, recursionLevel);
continue loopPrintGraph;
}
exHappened = true;
ipStart = ex.getIp();
@@ -2932,7 +2934,8 @@ public class Graph {
printGraph(foundGotos, partCodes, partCodePos, visited, localData, sPreLoop, allParts, part, currentLoop.loopBreak, stopPart, stopPartKind, loops, throwStates, ret, staticOperation, path, recursionLevel + 1);
}
}
break;
}
return ret;
}
@@ -3169,8 +3172,8 @@ public class Graph {
i--;
}
}
public static void makeAllCommands(List<GraphTargetItem> commands, TranslateStack stack) {
public void makeAllCommands(List<GraphTargetItem> commands, TranslateStack stack) {
int clen = commands.size();
boolean isExit = false;
if (clen > 0) {
@@ -21,6 +21,7 @@ import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Stack;
/**
*
@@ -73,11 +74,10 @@ public class GraphPart implements Serializable {
public int finishedTime;
public int order;
public int numBlocks = Integer.MAX_VALUE;
//public List<GraphPart> throwParts = new ArrayList<>();
public enum StopPartType {
NONE, AND_OR, COMMONPART
@@ -125,7 +125,7 @@ public class GraphPart implements Serializable {
ordered.add(this);
return time;
}
public void setNumblocks(int numBlocks) {
this.numBlocks = numBlocks;
numBlocks++;
@@ -133,7 +133,7 @@ public class GraphPart implements Serializable {
if (next.numBlocks > numBlocks) {
next.setNumblocks(numBlocks);
}
}
}
}
private boolean leadsTo(BaseLocalData localData, Graph gr, GraphSource code, GraphPart prev, GraphPart part, HashSet<GraphPart> visited, List<Loop> loops, List<ThrowState> throwStates, boolean useThrow) throws InterruptedException {
@@ -141,6 +141,74 @@ public class GraphPart implements Serializable {
throw new InterruptedException();
}
Stack<GraphPart> todo = new Stack<>();
todo.push(this);
looptodo:while (!todo.isEmpty()) {
GraphPart thisPart = todo.pop();
GraphPart tpart = gr.checkPart(null, localData, prev, thisPart, null);
if (tpart == null) {
continue;
}
if (tpart != thisPart) {
todo.push(tpart);
continue;
}
for (Loop l : loops) {
if (l.phase == 1) {
if (l.loopContinue == thisPart) {
continue looptodo;
}
if (l.loopPreContinue == thisPart) {
continue looptodo;
}
if (l.loopBreak == thisPart) {
//return false; //?
}
}
}
if (visited.contains(thisPart)) {
continue;
}
visited.add(thisPart);
if (thisPart.end < code.size() && code.get(thisPart.end).isBranch() && (code.get(thisPart.end).ignoredLoops())) {
continue;
}
for (GraphPart p : thisPart.nextParts) {
if (p == part) {
return true;
}
if (visited.contains(p)) {
continue;
}
todo.push(p);
}
for (ThrowState ts : throwStates) {
if (ts.state != 1) {
if (ts.throwingParts.contains(thisPart)) {
GraphPart p = ts.targetPart;
if (p == part) {
return true;
}
if (visited.contains(p)) {
continue;
}
todo.push(p);
}
}
}
}
return false;
}
private boolean leadsToRecursive(BaseLocalData localData, Graph gr, GraphSource code, GraphPart prev, GraphPart part, HashSet<GraphPart> visited, List<Loop> loops, List<ThrowState> throwStates, boolean useThrow) throws InterruptedException {
if (Thread.currentThread().isInterrupted()) {
throw new InterruptedException();
}
GraphPart tpart = gr.checkPart(null, localData, prev, this, null);
if (tpart == null) {
return false;
@@ -36,7 +36,7 @@ public abstract class GraphSource implements Serializable {
public abstract boolean isEmpty();
public abstract List<GraphTargetItem> translatePart(GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException;
public abstract List<GraphTargetItem> translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException;
public abstract Set<Long> getImportantAddresses();
@@ -48,6 +48,9 @@ public class CommaExpressionItem extends GraphTargetItem {
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
boolean first = true;
for (GraphTargetItem t : commands) {
if (t.isEmpty()) {
continue;
}
if (!first) {
writer.append(", ");
}
@@ -101,13 +101,15 @@ public class DoWhileItem extends LoopItem implements Block {
}
writer.append("(");
boolean first = true;
for (int i = 0; i < expression.size(); i++) {
if (expression.get(i).isEmpty()) {
continue;
}
if (i != 0) {
if (!first) {
writer.append(", ");
}
first = false;
if (i == expression.size() - 1) {
expression.get(i).toStringBoolean(writer, localData);
} else {
@@ -92,13 +92,15 @@ public class WhileItem extends LoopItem implements Block {
writer.append(" ");
}
writer.append("(");
boolean first = true;
for (int i = 0; i < expression.size(); i++) {
if (expression.get(i).isEmpty()) {
continue;
}
if (i != 0) {
if (!first) {
writer.append(", ");
}
first = false;
if (i == expression.size() - 1) {
expression.get(i).toStringBoolean(writer, localData);
} else {