diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ea1715c1..c7350e722 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -43,6 +43,7 @@ All notable changes to this project will be documented in this file. - AS1/2 both pcode and AS editable at the same time - AS3 direct editation - Allow some special words (like `override`) as identifiers - [#2486] AS1/2 if jump to function end as return +- [#2493] Incorrect placement of §§push instructions ### Changed - Icon of "Deobfuscation options" menu from pile of pills to medkit @@ -3933,6 +3934,7 @@ Major version of SWF to XML export changed to 2. [#1277]: https://www.free-decompiler.com/flash/issues/1277 [#2483]: https://www.free-decompiler.com/flash/issues/2483 [#2486]: https://www.free-decompiler.com/flash/issues/2486 +[#2493]: https://www.free-decompiler.com/flash/issues/2493 [#2476]: https://www.free-decompiler.com/flash/issues/2476 [#2404]: https://www.free-decompiler.com/flash/issues/2404 [#1418]: https://www.free-decompiler.com/flash/issues/1418 diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index d7f107338..912c08a1d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -1826,6 +1826,7 @@ public class AVM2Code implements Cloneable { /** * Converts to source output. * + * @param output Output * @param swfVersion SWF version * @param switchParts Switch parts * @param callStack Call stack @@ -1853,11 +1854,10 @@ public class AVM2Code implements Cloneable { * @param visited Visited * @param localRegAssignmentIps Local register assignment IPs * @param bottomStackSetLocals Set locals on bottom of the stack - * @return Convert output * @throws ConvertException On convert error * @throws InterruptedException On interrupt */ - public ConvertOutput toSourceOutput(int swfVersion, Set switchParts, List callStack, AbcIndexing abcIndex, Map> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, ABC abc, MethodBody body, int start, int end, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, boolean[] visited, HashMap localRegAssignmentIps, LinkedIdentityHashSet bottomStackSetLocals) throws ConvertException, InterruptedException { + public void toSourceOutput(List output, int swfVersion, Set switchParts, List callStack, AbcIndexing abcIndex, Map> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap localRegs, TranslateStack stack, ScopeStack scopeStack, ScopeStack localScopeStack, ABC abc, MethodBody body, int start, int end, HashMap localRegNames, HashMap localRegTypes, List fullyQualifiedNames, boolean[] visited, HashMap localRegAssignmentIps, LinkedIdentityHashSet bottomStackSetLocals) throws ConvertException, InterruptedException { boolean debugMode = DEBUG_MODE; if (debugMode) { System.err.println("OPEN SubSource:" + start + "-" + end + " " + code.get(start).toString() + " to " + code.get(end).toString()); @@ -1870,7 +1870,6 @@ public class AVM2Code implements Cloneable { if (toSourceLimit > 0 && toSourceCount >= toSourceLimit) { throw new ConvertException("Limit of subs(" + toSourceLimit + ") was reached", start); } - List output = new ArrayList<>(); int ip = start; //try { //int addr; @@ -2043,14 +2042,7 @@ public class AVM2Code implements Cloneable { } if (debugMode) { System.err.println("CLOSE SubSource:" + start + "-" + end + " " + code.get(start).toString() + " to " + code.get(end).toString()); - } - /*if (hideTemporaryRegisters) { - clearTemporaryRegisters(output); - }*/ - return new ConvertOutput(stack, output); - /*} catch (ConvertException cex) { - throw cex; - }*/ + } } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java index fe9c34a4d..9ca7076cd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegisters.java @@ -360,7 +360,7 @@ public class AVM2DeobfuscatorRegisters extends AVM2DeobfuscatorSimple { } @Override - public List translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException { + public void translatePart(List output, 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. } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java index 9410430c9..77a158814 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/deobfuscation/AVM2DeobfuscatorRegistersOld.java @@ -383,7 +383,7 @@ public class AVM2DeobfuscatorRegistersOld extends AVM2DeobfuscatorSimpleOld { } @Override - public List translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException { + public void translatePart(List output, 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. } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java index 424ec8dc3..22e1295d1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2Graph.java @@ -98,6 +98,7 @@ import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphException; import com.jpexs.decompiler.graph.GraphPart; import com.jpexs.decompiler.graph.GraphPartChangeException; +import com.jpexs.decompiler.graph.GraphPartMarkedArrayList; import com.jpexs.decompiler.graph.GraphSource; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -340,11 +341,11 @@ public class AVM2Graph extends Graph { //localData2.scopeStack = new ScopeStack(); localData2.localScopeStack = new ScopeStack(); - List targetOutput; + List targetOutput = new GraphPartMarkedArrayList<>(); try { - targetOutput = translatePart(localData2, finallyTryTargetPart, finallyTryTargetStack, 0 /*??*/, "try_target"); + translatePart(targetOutput, localData2, finallyTryTargetPart, finallyTryTargetStack, 0 /*??*/, "try_target"); } catch (GraphPartChangeException ex1) { //should not happen - targetOutput = new ArrayList<>(); + targetOutput.clear(); } int switchedReg = -1; @@ -1173,9 +1174,9 @@ public class AVM2Graph extends Graph { if (finallyIndex > -1) { parsedExceptionIds.add(finallyIndex); } - List tryCommands = new ArrayList<>(); - List> catchCommands = new ArrayList<>(); - List finallyCommands = new ArrayList<>(); + List tryCommands = new GraphPartMarkedArrayList<>(); + List> catchCommands = new GraphPartMarkedArrayList<>(); + List finallyCommands = new GraphPartMarkedArrayList<>(); GraphPart afterPart = null; @@ -1255,7 +1256,7 @@ public class AVM2Graph extends Graph { boolean inlinedFinally = false; boolean finallyAsUnnamedException = false; - List finallyTargetItems = new ArrayList<>(); + List finallyTargetItems = new GraphPartMarkedArrayList<>(); GraphPart defaultPart = null; GraphPart finallyPart = null; @@ -1289,12 +1290,12 @@ public class AVM2Graph extends Graph { AVM2LocalData localData2 = new AVM2LocalData(localData); //localData2.scopeStack = new ScopeStack(); localData2.localScopeStack = new ScopeStack(); - + try { //We are assuming Finally target has only 1 part - finallyTargetItems = translatePart(localData2, finallyTryTargetPart, st2, staticOperation, path); + translatePart(finallyTargetItems, localData2, finallyTryTargetPart, st2, staticOperation, path); } catch (GraphPartChangeException ex) { //should not happen - finallyTargetItems = new ArrayList<>(); + finallyTargetItems.clear(); } //boolean targetHasThrow = false; if (!finallyTargetItems.isEmpty() && (finallyTargetItems.get(finallyTargetItems.size() - 1) instanceof ThrowAVM2Item)) { @@ -1385,9 +1386,10 @@ public class AVM2Graph extends Graph { } if (switchPart != null) { try { - finallyCommands.addAll(translatePart(localData, switchPart, stack, staticOperation, path)); + translatePart(finallyCommands, localData, switchPart, stack, staticOperation, path); } catch (GraphPartChangeException ex) { //should not happen + finallyCommands.clear(); } stack.pop(); //value switched by lookupswitch } @@ -2249,13 +2251,21 @@ public class AVM2Graph extends Graph { } } + int firstPushPos = -1; + for (int i = output.size() - 2 /*last is loop*/; i >= 0; i--) { if (output.get(i) instanceof PushItem) { - PushItem pu = (PushItem) output.remove(i); - stack.push(pu.value); + firstPushPos = i; } else { break; } + } + if (firstPushPos > -1) { + int max = output.size() - 2; + for (int i = firstPushPos; i <= max; i++) { + PushItem pu = (PushItem) output.remove(firstPushPos); + stack.push(pu.value); + } } if (usages.isEmpty()) { output.add(filter); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java index 88559a1bf..0c36b58b6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/graph/AVM2GraphSource.java @@ -188,6 +188,7 @@ public class AVM2GraphSource extends GraphSource { /** * Translates the part of the graph source * + * @param output Output * @param graph Graph * @param part Graph part * @param localData Local data @@ -196,17 +197,13 @@ public class AVM2GraphSource extends GraphSource { * @param end End position * @param staticOperation Unused * @param path Path - * @return List of graph target items * @throws InterruptedException On interrupt */ @Override - public List translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException { - List ret = new ArrayList<>(); + public void translatePart(List output, Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException { Reference lineStartItem = new Reference<>(localData.lineStartInstruction); - ConvertOutput co = code.toSourceOutput(localData.swfVersion, localData.allSwitchParts, ((AVM2LocalData) localData).callStack, ((AVM2LocalData) localData).abcIndex, ((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, ((AVM2LocalData) localData).scopeStack, ((AVM2LocalData) localData).localScopeStack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, fullyQualifiedNames, new boolean[size()], localRegAssignmentIps, ((AVM2LocalData) localData).bottomSetLocals); - localData.lineStartInstruction = lineStartItem.getVal(); - ret.addAll(co.output); - return ret; + code.toSourceOutput(output, localData.swfVersion, localData.allSwitchParts, ((AVM2LocalData) localData).callStack, ((AVM2LocalData) localData).abcIndex, ((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, ((AVM2LocalData) localData).scopeStack, ((AVM2LocalData) localData).localScopeStack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, fullyQualifiedNames, new boolean[size()], localRegAssignmentIps, ((AVM2LocalData) localData).bottomSetLocals); + localData.lineStartInstruction = lineStartItem.getVal(); } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java index e806a7219..7ba406edf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/Action.java @@ -1225,6 +1225,7 @@ public abstract class Action implements GraphSourceItem { /** * Converts list of actions to tree. * + * @param output Output * @param graph ActionGraph * @param switchParts Switch parts * @param secondPassData Second pass data @@ -1241,17 +1242,15 @@ public abstract class Action implements GraphSourceItem { * @param staticOperation Static operation * @param path Path * @param charset Charset - * @return List of tree items * @throws InterruptedException On interrupt * @throws GraphPartChangeException On graph part change */ - public static List actionsPartToTree(ActionGraph graph, Set switchParts, SecondPassData secondPassData, boolean insideDoInitAction, Reference lineStartActionRef, HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List actions, int start, int end, int version, int staticOperation, String path, String charset) throws InterruptedException, GraphPartChangeException { + public static void actionsPartToTree(List output, ActionGraph graph, Set switchParts, SecondPassData secondPassData, boolean insideDoInitAction, Reference lineStartActionRef, HashMap registerNames, HashMap variables, HashMap functions, TranslateStack stack, List 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) + ")") : ""}); } ActionLocalData localData = new ActionLocalData(switchParts, secondPassData, insideDoInitAction, registerNames, variables, functions, graph.getUninitializedClassTraits()); localData.lineStartAction = lineStartActionRef.getVal(); - List output = new ArrayList<>(); int ip = start; boolean isWhile = false; boolean isForIn = false; @@ -1389,8 +1388,7 @@ public abstract class Action implements GraphSourceItem { if (ip > end + 1) { throw new GraphPartChangeException(output, ip); } - logger.log(Level.FINE, "Leaving {0}-{1}", new Object[]{start, end}); - return output; + logger.log(Level.FINE, "Leaving {0}-{1}", new Object[]{start, end}); } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java index cb210c232..b33ab53bf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraphSource.java @@ -197,6 +197,7 @@ public class ActionGraphSource extends GraphSource { /** * Translates the part of the graph source * + * @param output Output * @param graph Graph * @param part Graph part * @param localData Local data @@ -210,12 +211,11 @@ public class ActionGraphSource extends GraphSource { * @throws GraphPartChangeException On graph part change */ @Override - public List translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException { + public void translatePart(List output, Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException { Reference fi = new Reference<>(localData.lineStartInstruction); - List r = Action.actionsPartToTree((ActionGraph) graph, localData.allSwitchParts, localData.secondPassData, this.insideDoInitAction, fi, registerNames, variables, functions, stack, actions, start, end, version, staticOperation, path, charset); + Action.actionsPartToTree(output, (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; } /** diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index 9698b7a4d..4320541e9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -27,7 +27,6 @@ import com.jpexs.decompiler.graph.model.BinaryOpItem; import com.jpexs.decompiler.graph.model.BranchStackResistant; import com.jpexs.decompiler.graph.model.BreakItem; import com.jpexs.decompiler.graph.model.CommaExpressionItem; -import com.jpexs.decompiler.graph.model.CommentItem; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.DefaultItem; import com.jpexs.decompiler.graph.model.DoWhileItem; @@ -2354,7 +2353,7 @@ public class Graph { //@SuppressWarnings("unchecked") protected final GraphTargetItem translatePartGetStack(BaseLocalData localData, GraphPart part, TranslateStack stack, int staticOperation) throws InterruptedException, GraphPartChangeException { stack = (TranslateStack) stack.clone(); - translatePart(localData, part, stack, staticOperation, null); + translatePart(new ArrayList<>(), localData, part, stack, staticOperation, null); return stack.pop(); } @@ -2373,13 +2372,14 @@ public class Graph { protected final GraphTargetItem translatePartGetStack(BaseLocalData localData, GraphPart part, TranslateStack stack, int staticOperation, List output) throws InterruptedException, GraphPartChangeException { stack = (TranslateStack) stack.clone(); output.clear(); - output.addAll(translatePart(localData, part, stack, staticOperation, null)); + translatePart(output, localData, part, stack, staticOperation, null); return stack.pop(); } /** * Translates part. * + * @param output Output * @param localData Local data * @param part Part * @param stack Translate stack @@ -2389,9 +2389,8 @@ public class Graph { * @throws InterruptedException On interrupt * @throws GraphPartChangeException On graph part change */ - protected final List translatePart(BaseLocalData localData, GraphPart part, TranslateStack stack, int staticOperation, String path) throws InterruptedException, GraphPartChangeException { + protected final void translatePart(List output, BaseLocalData localData, GraphPart part, TranslateStack stack, int staticOperation, String path) throws InterruptedException, GraphPartChangeException { List sub = part.getSubParts(); - List ret = new ArrayList<>(); int end; for (GraphPart p : sub) { if (p.end == -1) { @@ -2404,9 +2403,8 @@ public class Graph { } end = p.end; int start = p.start; - ret.addAll(code.translatePart(this, part, localData, stack, start, end, staticOperation, path)); + code.translatePart(output, this, part, localData, stack, start, end, staticOperation, path); } - return ret; } /** @@ -3469,6 +3467,7 @@ public class Graph { if (currentRet instanceof GraphPartMarkedArrayList) { ((GraphPartMarkedArrayList) currentRet).startPart(part); } + stack.setConnectedOutput(0, currentRet); if (checkPartOutput(currentRet, foundGotos, partCodes, partCodePos, visited, code, localData, allParts, stack, parent, part, stopPart, stopPartKind, loops, throwStates, currentLoop, staticOperation, path, recursionLevel)) { parseNext = false; } else { @@ -3477,9 +3476,10 @@ public class Graph { do { exHappened = false; try { - output.addAll(code.translatePart(this, part, localData, stack, ipStart, part.end, staticOperation, path)); + stack.setConnectedOutput(currentRet.size(), output); + code.translatePart(output, 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()); + //output.addAll(ex.getOutput()); for (GraphPart p : allParts) { if (p.containsIP(ex.getIp())) { if (ex.getIp() == p.start) { @@ -4542,7 +4542,12 @@ public class Graph { //ASC2 leaves some function calls unpopped on stack before returning from a method commands.add(clen, p); } else { - commands.add(clen, new PushItem(p)); + int pos = 0; + if (p.outputPos < commands.size()) { + commands.add(p.outputPos, new PushItem(p)); + } else { + commands.add(clen + pos, new PushItem(p)); + } } } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSource.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSource.java index 1e010a4d1..d3d19891d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSource.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphSource.java @@ -62,6 +62,7 @@ public abstract class GraphSource implements Serializable { /** * Translates the part of the graph source * + * @param output Output * @param graph Graph * @param part Graph part * @param localData Local data @@ -70,11 +71,10 @@ public abstract class GraphSource implements Serializable { * @param end End position * @param staticOperation Unused * @param path Path - * @return List of graph target items * @throws InterruptedException On interrupt * @throws GraphPartChangeException On graph part change */ - public abstract List translatePart(Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException; + public abstract void translatePart(List output, Graph graph, GraphPart part, BaseLocalData localData, TranslateStack stack, int start, int end, int staticOperation, String path) throws InterruptedException, GraphPartChangeException; /** * Gets the important addresses diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java index e2534bd61..ba2c3125d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -128,7 +128,12 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { * Dialect */ public GraphTargetDialect dialect; - + + /** + * Position in output - current list of GraphTargetItems + */ + public int outputPos = -1; + /** * Gets the line start item * diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java index 6163ac9af..0976e92bf 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/TranslateStack.java @@ -18,6 +18,7 @@ package com.jpexs.decompiler.graph; import com.jpexs.decompiler.graph.model.PopItem; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.Stack; import java.util.logging.Level; @@ -39,9 +40,25 @@ public class TranslateStack extends Stack { * Path */ private final String path; + + private List connectedOutput = null; + + private int prevOutputSize = 0; private Map marks = new HashMap<>(); + public void setConnectedOutput(int prevOutputSize, List connectedOutput) { + this.prevOutputSize = prevOutputSize; + this.connectedOutput = connectedOutput; + } + + @Override + public GraphTargetItem push(GraphTargetItem item) { + if (connectedOutput != null && item != null) { + item.outputPos = prevOutputSize + connectedOutput.size(); + } + return super.push(item); + } /** * Sets mark. diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java index 9b5192244..95b392931 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java @@ -313,6 +313,24 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT false); } + @Test + public void testPushPlacement() { + decompileMethod("assembled", "testPushPlacement", "var a:int = 1;\r\n" + + "var b:* = 2;\r\n" + + "§§push(a);\r\n" + + "a += 1;\r\n" + + "if(b >= 2)\r\n" + + "{\r\n" + + "b = §§pop() + 7;\r\n" + + "trace(b);\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "§§pop();\r\n" + + "}\r\n", + false); + } + @Test public void testPushWhile() { decompileMethod("assembled", "testPushWhile", "var _loc3_:int = 5;\r\n" @@ -440,33 +458,33 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT + "case 1:\r\n" + "case 6:\r\n" + "trace(\"1-6\");\r\n" - + "addr0120:\r\n" + + "addr0121:\r\n" + "trace(\"F\");\r\n" + "break;\r\n" + "case 5:\r\n" + "trace(\"5\");\r\n" - + "addr0119:\r\n" + + "addr011a:\r\n" + "trace(\"E\");\r\n" - + "§§goto(addr0120);\r\n" + + "§§goto(addr0121);\r\n" + "case 7:\r\n" + "trace(\"7\");\r\n" - + "addr0112:\r\n" + + "addr0113:\r\n" + "trace(\"D\");\r\n" - + "§§goto(addr0119);\r\n" + + "§§goto(addr011a);\r\n" + "case 2:\r\n" + "trace(\"2\");\r\n" - + "addr010b:\r\n" + + "addr010c:\r\n" + "trace(\"C\");\r\n" - + "§§goto(addr0112);\r\n" + + "§§goto(addr0113);\r\n" + "case 8:\r\n" + "trace(\"8\");\r\n" - + "addr0104:\r\n" + + "addr0105:\r\n" + "trace(\"B\");\r\n" - + "§§goto(addr010b);\r\n" + + "§§goto(addr010c);\r\n" + "default:\r\n" + "trace(\"def\");\r\n" + "trace(\"A\");\r\n" - + "§§goto(addr0104);\r\n" + + "§§goto(addr0105);\r\n" + "}\r\n" + "trace(\"G\");\r\n" + "return null;\r\n", diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc index 17a3ba11b..f5ec7afc1 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc and b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc differ diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm index f3fd6eeea..96276599b 100644 --- a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm @@ -39,5 +39,6 @@ program #include "tests/TestGoto2.script.asasm" #include "tests/TestAlwaysBreak.script.asasm" #include "tests/TestAlwaysBreak2.script.asasm" + #include "tests/TestPushPlacement.script.asasm" ; place to add next end ; program diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestPushPlacement.class.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestPushPlacement.class.asasm new file mode 100644 index 000000000..0582895ab --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestPushPlacement.class.asasm @@ -0,0 +1,87 @@ +class + refid "tests:TestPushPlacement" + instance QName(PackageNamespace("tests"), "TestPushPlacement") + extends QName(PackageNamespace(""), "Object") + flag SEALED + flag PROTECTEDNS + protectedns ProtectedNamespace("tests:TestPushPlacement") + iinit + refid "tests:TestPushPlacement/instance/init" + body + maxstack 1 + localcount 1 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + + getlocal0 + constructsuper 0 + + returnvoid + end ; code + end ; body + end ; method + trait method QName(PackageNamespace(""), "run") + method + refid "tests:TestPushPlacement/instance/run" + returns QName(PackageNamespace(""), "void") + body + maxstack 2 + localcount 4 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + debug 1, "a", 0, 13 + debug 1, "b", 1, 14 + pushbyte 1 + convert_i + setlocal1 + pushbyte 2 + coerce_a + setlocal2 + getlocal1 + getlocal1 + pushbyte 1 + add + convert_i + setlocal1 + getlocal2 + pushbyte 2 + ifnge ofs0031 + pushbyte 7 + add + coerce_a + setlocal2 + findpropstrict QName(PackageNamespace(""),"trace") + getlocal2 + callpropvoid QName(PackageNamespace(""),"trace"), 1 + jump ofs0032 + ofs0031: + pop + ofs0032: + returnvoid + end ; code + end ; body + end ; method + end ; trait + end ; instance + cinit + refid "tests:TestPushPlacement/class/init" + body + maxstack 1 + localcount 1 + initscopedepth 3 + maxscopedepth 4 + code + getlocal0 + pushscope + + returnvoid + end ; code + end ; body + end ; method +end ; class diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestPushPlacement.script.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestPushPlacement.script.asasm new file mode 100644 index 000000000..9c1b48812 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestPushPlacement.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestPushPlacement/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestPushPlacement", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestPushPlacement"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestPushPlacement" + popscope + initproperty QName(PackageNamespace("tests"), "TestPushPlacement") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestPushPlacement") + #include "TestPushPlacement.class.asasm" + end ; trait +end ; script diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf b/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf index 692633add..7e05cf57c 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf and b/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf differ