Fixed AS1/2 switch with nontrivial expressions - secondpass for all strictequals

This commit is contained in:
Jindra Petřík
2021-11-28 19:54:29 +01:00
parent 3033f1f39f
commit 2390b1840c
4 changed files with 84 additions and 25 deletions

View File

@@ -86,6 +86,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -930,9 +931,15 @@ public abstract class Action implements GraphSourceItem {
* @throws java.lang.InterruptedException
*/
public static List<GraphTargetItem> actionsToTree(boolean insideDoInitAction, boolean insideFunction, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, List<Action> actions, int version, int staticOperation, String path) throws InterruptedException {
HashMap<String, GraphTargetItem> variablesBackup = new LinkedHashMap<>(variables);
HashMap<String, GraphTargetItem> functionsBackup = new LinkedHashMap<>(functions);
try {
return ActionGraph.translateViaGraph(null, insideDoInitAction, insideFunction, regNames, variables, functions, actions, version, staticOperation, path);
} catch (SecondPassException spe) {
variables.clear();
variables.putAll(variablesBackup);
functions.clear();
functions.putAll(functionsBackup);
return ActionGraph.translateViaGraph(spe.getData(), insideDoInitAction, insideFunction, regNames, variables, functions, actions, version, staticOperation, path);
}
}
@@ -982,6 +989,18 @@ public abstract class Action implements GraphSourceItem {
this.ignored = ignored;
}
private static HashMap<String, GraphTargetItem> prepareVariables(GraphSourceItemContainer cnt, HashMap<String, GraphTargetItem> variables) {
HashMap<String, GraphTargetItem> variables2 = Helper.deepCopy(variables);
if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) {
for (int r = 0; r < 256; r++) {
if (variables2.containsKey("__register" + r)) {
variables2.remove("__register" + r);
}
}
}
return variables2;
}
public static List<GraphTargetItem> actionsPartToTree(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) 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) + ")") : ""});
@@ -1033,14 +1052,7 @@ public abstract class Action implements GraphSourceItem {
long endAddr = action.getAddress() + cnt.getHeaderSize();
String cntName = cnt.getName();
List<List<GraphTargetItem>> outs = new ArrayList<>();
HashMap<String, GraphTargetItem> variables2 = Helper.deepCopy(variables);
if (cnt instanceof ActionDefineFunction || cnt instanceof ActionDefineFunction2) {
for (int r = 0; r < 256; r++) {
if (variables2.containsKey("__register" + r)) {
variables2.remove("__register" + r);
}
}
}
HashMap<String, GraphTargetItem> variables2 = prepareVariables(cnt, variables);
for (long size : cnt.getContainerSizes()) {
if (size == 0) {
outs.add(new ArrayList<>());
@@ -1056,7 +1068,12 @@ public abstract class Action implements GraphSourceItem {
}
}
}
out = ActionGraph.translateViaGraph(secondPassData, insideDoInitAction, true, regNames, variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName));
try {
out = ActionGraph.translateViaGraph(null, insideDoInitAction, true, regNames, variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName));
} catch (SecondPassException spe) {
variables2 = prepareVariables(cnt, variables);
out = ActionGraph.translateViaGraph(spe.getData(), insideDoInitAction, true, regNames, variables2, functions, actions.subList(adr2ip(actions, endAddr), adr2ip(actions, endAddr + size)), version, staticOperation, path + (cntName == null ? "" : "/" + cntName));
}
} catch (OutOfMemoryError | TranslateException | StackOverflowError ex) {
logger.log(Level.SEVERE, "Decompilation error in: " + path, ex);
if (ex instanceof OutOfMemoryError) {

View File

@@ -398,6 +398,15 @@ public class ActionGraph extends Graph {
}
}
private GraphPart findPart(int ip, Set<GraphPart> allParts) {
for (GraphPart p : allParts) {
if (p.containsIP(ip)) {
return p;
}
}
return null;
}
@Override
protected List<GraphTargetItem> check(List<GraphTargetItem> currentRet, List<GotoItem> foundGotos, Map<GraphPart, List<GraphTargetItem>> partCodes, Map<GraphPart, Integer> partCodePos, Set<GraphPart> visited, GraphSource code, BaseLocalData localData, Set<GraphPart> allParts, TranslateStack stack, GraphPart parent, GraphPart part, List<GraphPart> stopPart, List<StopPartKind> stopPartKind, List<Loop> loops, List<ThrowState> throwStates, List<GraphTargetItem> output, Loop currentLoop, int staticOperation, String path) throws InterruptedException {
if (!output.isEmpty()) {
@@ -445,29 +454,31 @@ public class ActionGraph extends Graph {
if (secondPassData != null) {
for (int si = 0; si < secondPassData.switchParts.size(); si++) {
if (secondPassData.switchParts.get(si).get(0).equals(part)) {
part = secondPassData.switchParts.get(si).get(secondPassData.switchParts.get(si).size() - 1);
//we need to use findpart as parts have changed between first and second pass
part = findPart(secondPassData.switchParts.get(si).get(secondPassData.switchParts.get(si).size() - 1).start, allParts);
caseBodyParts.clear();
caseBodyParts.addAll(secondPassData.switchOnFalseParts.get(si));
for (GraphPart p : secondPassData.switchOnFalseParts.get(si)) {
caseBodyParts.add(findPart(p.start, allParts));
}
caseValuesMap.clear();
caseValuesMap.addAll(secondPassData.switchCaseExpressions.get(si));
secondSwitchFound = true;
}
}
}
int cnt = 1;
if (!secondSwitchFound) {
if (false) { //always do secondPass
try {
while (part.nextParts.size() > 1
&& part.nextParts.get(1).getHeight() > 1
&& code.get(part.nextParts.get(1).end >= code.size() ? code.size() - 1 : part.nextParts.get(1).end) instanceof ActionIf
&& ((top = translatePartGetStack(localData, part.nextParts.get(1), stack, staticOperation)) instanceof StrictEqActionItem)) {
cnt++;
part = part.nextParts.get(1);
caseBodyParts.add(part.nextParts.get(0));
while (part.nextParts.size() > 1
&& part.nextParts.get(1).getHeight() > 1
&& code.get(part.nextParts.get(1).end >= code.size() ? code.size() - 1 : part.nextParts.get(1).end) instanceof ActionIf
&& ((top = translatePartGetStack(localData, part.nextParts.get(1), stack, staticOperation)) instanceof StrictEqActionItem)) {
cnt++;
part = part.nextParts.get(1);
caseBodyParts.add(part.nextParts.get(0));
set = (StrictEqActionItem) top;
caseValuesMap.add(set.rightSide);
set = (StrictEqActionItem) top;
caseValuesMap.add(set.rightSide);
}
} catch (GraphPartChangeException gce) {
//ignore
@@ -555,9 +566,16 @@ public class ActionGraph extends Graph {
List<GraphTargetItem> switchExpressions = new ArrayList<>();
List<GraphPart> switchOnFalseParts = new ArrayList<>();
BinaryOpItem sneq = (BinaryOpItem) ii.expression;
if (sneq.leftSide instanceof StoreRegisterActionItem) {
StoreRegisterActionItem sr = (StoreRegisterActionItem) sneq.leftSide;
int regId = sr.register.number;
if ((sneq.leftSide instanceof StoreRegisterActionItem) || (sneq.leftSide instanceof GetVariableActionItem)) {
int regId = -1;
GetVariableActionItem svar = null;
if (sneq.leftSide instanceof StoreRegisterActionItem) {
StoreRegisterActionItem sr = (StoreRegisterActionItem) sneq.leftSide;
regId = sr.register.number;
} else {
svar = (GetVariableActionItem) sneq.leftSide;
}
switchParts.add(ii.decisionPart);
switchExpressions.add(sneq.rightSide);
@@ -586,6 +604,15 @@ public class ActionGraph extends Graph {
} else {
break;
}
} else if (svar != null && sneq.leftSide instanceof GetVariableActionItem) {
if (sneq.leftSide.valueEquals(svar)) {
switchParts.add(ii2.decisionPart);
switchOnFalseParts.add(ii2.onTruePart);
switchExpressions.add(sneq.rightSide);
walkNext.add(isNeq ? ii2.onFalse : ii2.onTrue);
} else {
break;
}
} else {
break;
}

View File

@@ -39,6 +39,7 @@ import com.jpexs.decompiler.graph.TranslateStack;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
@@ -106,9 +107,16 @@ public class ActionWaitForFrame extends Action implements ActionStore {
public void translate(SecondPassData secondPassData, boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) throws InterruptedException {
GraphTargetItem frameTi = new DirectValueActionItem(null, null, 0, (Long) ((long) frame), new ArrayList<>());
List<GraphTargetItem> body;
HashMap<String, GraphTargetItem> variablesBackup = new LinkedHashMap<>(variables);
HashMap<String, GraphTargetItem> functionsBackup = new LinkedHashMap<>(functions);
try {
body = ActionGraph.translateViaGraph(null, insideDoInitAction, true, regNames, variables, functions, skipped, SWF.DEFAULT_VERSION, staticOperation, path);
} catch (SecondPassException spe) {
variables.clear();
variables.putAll(variablesBackup);
functions.clear();
functions.putAll(functionsBackup);
body = ActionGraph.translateViaGraph(spe.getData(), insideDoInitAction, true, regNames, variables, functions, skipped, SWF.DEFAULT_VERSION, staticOperation, path);
}
output.add(new IfFrameLoadedActionItem(frameTi, body, this, lineStartAction));

View File

@@ -38,6 +38,7 @@ import com.jpexs.decompiler.graph.TranslateStack;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Set;
@@ -151,9 +152,15 @@ public class ActionWaitForFrame2 extends Action implements ActionStore {
public void translate(SecondPassData secondPassData, boolean insideDoInitAction, GraphSourceItem lineStartAction, TranslateStack stack, List<GraphTargetItem> output, HashMap<Integer, String> regNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, int staticOperation, String path) throws InterruptedException {
GraphTargetItem frame = stack.pop();
List<GraphTargetItem> body;
HashMap<String, GraphTargetItem> variablesBackup = new LinkedHashMap<>(variables);
HashMap<String, GraphTargetItem> functionsBackup = new LinkedHashMap<>(functions);
try {
body = ActionGraph.translateViaGraph(null, insideDoInitAction, true, regNames, variables, functions, skipped, SWF.DEFAULT_VERSION, staticOperation, path);
} catch (SecondPassException spe) {
variables.clear();
variables.putAll(variablesBackup);
functions.clear();
functions.putAll(functionsBackup);
body = ActionGraph.translateViaGraph(spe.getData(), insideDoInitAction, true, regNames, variables, functions, skipped, SWF.DEFAULT_VERSION, staticOperation, path);
}
output.add(new IfFrameLoadedActionItem(frame, body, this, lineStartAction));