diff --git a/CHANGELOG.md b/CHANGELOG.md index c94f04b89..878e9b2a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,10 @@ # Change Log All notable changes to this project will be documented in this file. +## [Unreleased] +### Fixed +- AS3 break loop in catch clause + ## [13.0.0] - 2021-02-08 ### Added - Graphviz graphs colorized 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 9287a51be..8d9ba6e84 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 @@ -21,8 +21,10 @@ import com.jpexs.decompiler.flash.FinalProcessLocalData; import com.jpexs.decompiler.flash.abc.ABC; import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; +import com.jpexs.decompiler.flash.abc.avm2.CodeStats; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewCatchIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.debug.DebugLineIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.IfStrictEqIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.jumps.JumpIns; @@ -32,6 +34,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.GetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.KillIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.HasNext2Ins; import com.jpexs.decompiler.flash.abc.avm2.instructions.other.LabelIns; @@ -43,6 +46,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.DecLocalPIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.other2.IncLocalPIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PopIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushByteIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceAIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.types.ConvertIIns; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; @@ -166,10 +170,15 @@ public class AVM2Graph extends Graph { } @Override - protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part) { - AVM2LocalData aLocalData = (AVM2LocalData) localData; + protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part, List throwStates) { + /*AVM2LocalData aLocalData = (AVM2LocalData) localData; if (aLocalData.finallyTargetParts.containsValue(part)) { return false; + }*/ + for (ThrowState ts : throwStates) { + if (ts.targetPart == part) { + return false; + } } return true; } @@ -177,7 +186,6 @@ public class AVM2Graph extends Graph { @Override protected void beforeGetLoops(BaseLocalData localData, String path, Set allParts, List throwStates) throws InterruptedException { AVM2LocalData avm2LocalData = ((AVM2LocalData) localData); - for (int e = 0; e < body.exceptions.length; e++) { ABCException ex = body.exceptions[e]; if (ex.isFinally()) { @@ -185,7 +193,6 @@ public class AVM2Graph extends Graph { } } - avm2LocalData.codeStats = avm2LocalData.code.getStats(avm2LocalData.abc, avm2LocalData.methodBody, avm2LocalData.methodBody.init_scope_depth, false); getIgnoredSwitches((AVM2LocalData) localData, allParts); Set integerSwitchesIps = new HashSet<>(); for (GraphPart p : avm2LocalData.ignoredSwitches.values()) { @@ -2065,7 +2072,11 @@ public class AVM2Graph extends Graph { } @Override - protected List getThrowStates(Set allParts) { + protected List getThrowStates(BaseLocalData localData, Set allParts) { + + AVM2LocalData avm2LocalData = (AVM2LocalData) localData; + avm2LocalData.codeStats = avm2LocalData.code.getStats(avm2LocalData.abc, avm2LocalData.methodBody, avm2LocalData.methodBody.init_scope_depth, false); + List ret = new ArrayList<>(); for (int e = 0; e < body.exceptions.length; e++) { ThrowState ts = new ThrowState(); @@ -2079,9 +2090,113 @@ public class AVM2Graph extends Graph { ts.throwingParts.add(p); } } + GraphPart part = ts.targetPart; + boolean wasNewCatch = false; + int scopePos = -1; + int ip = part.start; + for (; ip <= part.end; ip++) { + + if (avm2code.code.get(ip).definition instanceof NewCatchIns) { + wasNewCatch = true; + } + if (avm2code.code.get(ip).definition instanceof PushScopeIns) { + if (wasNewCatch) { + scopePos = avm2LocalData.codeStats.instructionStats[ip].scopepos_after; + break; + } + } + if (ip == part.end && part.nextParts.size() == 1 && part.nextParts.get(0).refs.size() == 1) { + part = part.nextParts.get(0); + ip = part.start - 1; + continue; + } + } + + //Search all parts which have same or greater scope level, these all belong to catch + Set catchParts = new HashSet<>(); + if (scopePos > -1) { + walkCatchParts(avm2LocalData.codeStats, part, ip, catchParts, scopePos); + } else { + logger.fine("No newcatch..pushscope found in catch, probably swftools"); + part = ts.targetPart; + ip = part.start; + int localRegId = -1; + for (; ip <= part.end; ip++) { + AVM2Instruction ins = avm2code.code.get(ip); + if ((ins.definition instanceof NopIns) + || (ins.definition instanceof DebugLineIns) + || (ins.definition instanceof JumpIns)) { + //ignore + } else if (ins.definition instanceof SetLocalTypeIns) { + localRegId = (((SetLocalTypeIns) ins.definition).getRegisterId(ins)); + break; + } else { + break; + } + if (ip == part.end && part.nextParts.size() == 1 && part.nextParts.get(0).refs.size() == 1) { + part = part.nextParts.get(0); + ip = part.start - 1; + continue; + } + } + if (localRegId == -1) { + logger.fine("Not even local reg assignment found in catch, weird :-("); + } else { + walkCatchPartsReg(localRegId, part, ip + 1, catchParts, new ArrayList<>(), new HashSet<>()); + } + } + ts.catchParts = catchParts; ret.add(ts); } return ret; } + private void walkCatchPartsReg(int registerId, GraphPart part, int startIp, Set catchParts, List path, Set visited) { + if (visited.contains(part)) { + return; + } + visited.add(part); + List newPath = new ArrayList<>(path); + newPath.add(part); + for (int ip = startIp; ip <= part.end; ip++) { + AVM2Instruction ins = avm2code.code.get(ip); + if (ins.definition instanceof SetLocalTypeIns) { + int setLocalId = ((SetLocalTypeIns) ins.definition).getRegisterId(ins); + if (setLocalId == registerId) { + return; + } + } + if (ins.definition instanceof KillIns) { + int killId = ins.operands[0]; + if (killId == registerId) { + return; + } + } + if (ins.definition instanceof GetLocalTypeIns) { + int getLocalId = ((GetLocalTypeIns) ins.definition).getRegisterId(ins); + if (getLocalId == registerId) { + catchParts.addAll(newPath); + } + } + } + for (GraphPart n : part.nextParts) { + walkCatchPartsReg(registerId, n, n.start, catchParts, newPath, visited); + } + } + + private void walkCatchParts(CodeStats stats, GraphPart part, int startIp, Set catchParts, int scopePos) { + if (catchParts.contains(part)) { + return; + } + catchParts.add(part); + for (int ip = startIp; ip <= part.end; ip++) { + if (stats.instructionStats[ip].scopepos_after < scopePos) { + return; + } + } + for (GraphPart n : part.nextParts) { + walkCatchParts(stats, n, n.start, catchParts, scopePos); + } + } + } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java index 9c60ca11b..a52575955 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionGraph.java @@ -143,7 +143,7 @@ public class ActionGraph extends Graph { } @Override - protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part) { + protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part, List throwStates) { if (part.refs.size() <= 1) { return true; } 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 f9a04f365..a5511e574 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -481,7 +481,7 @@ public class Graph { } - protected List getThrowStates(Set allParts) { + protected List getThrowStates(BaseLocalData localData, Set allParts) { return new ArrayList<>(); } @@ -512,7 +512,7 @@ public class Graph { System.err.println("/parts"); } TranslateStack stack = new TranslateStack(path); - List throwStates = getThrowStates(allParts); + List throwStates = getThrowStates(localData, allParts); beforeGetLoops(localData, path, allParts, throwStates); List loops = new ArrayList<>(); @@ -1170,7 +1170,7 @@ public class Graph { clearThrowStates(throwStates); } - protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part) { + protected boolean canBeBreakCandidate(BaseLocalData localData, GraphPart part, List throwStates) { return true; } @@ -1207,11 +1207,8 @@ public class Graph { } checkGetLoopsPart(part); - List currentThrowStates = new ArrayList<>(); - for (ThrowState ts : throwStates) { - if (ts.throwingParts.contains(part) && ts.state != 1) { - currentThrowStates.add(ts); + if (ts.throwingParts.contains(part)) { ts.state = 1; } } @@ -1232,7 +1229,17 @@ public class Graph { } } - if (lastP1 != null && canBeBreakCandidate(localData, part)) { + + boolean canBeCandidate = true; + if (lastP1 != null) { + for (ThrowState ts : throwStates) { + if (!ts.catchParts.contains(lastP1.loopContinue) && ts.catchParts.contains(part)) { + canBeCandidate = false; + break; + } + } + } + if (lastP1 != null && canBeCandidate && canBeBreakCandidate(localData, part, throwStates)) { if (lastP1.breakCandidates.contains(part)) { lastP1.breakCandidates.add(part); lastP1.breakCandidatesLevels.add(level); @@ -1274,6 +1281,15 @@ public class Graph { //loopContinues.add(part); } + for (ThrowState ts : throwStates) { + if (ts.throwingParts.contains(part)) { + GraphPart t = ts.targetPart; + if (!visited.contains(t)) { + getLoopsWalk(localData, t, loops, throwStates, stopPart, false, visited, level); + } + } + } + if (part.nextParts.size() == 2 && !partIsSwitch(part)) { List nps;/* = new ArrayList<>(part.nextParts); @@ -1326,22 +1342,13 @@ public class Graph { getLoopsWalk(localData, part.nextParts.get(0), loops, throwStates, stopPart, false, visited, level); } - List loops2 = new ArrayList<>(loops); + /*List loops2 = new ArrayList<>(loops); for (Loop l : loops2) { l.breakCandidatesLocked++; - } - for (ThrowState ts : throwStates) { - if (ts.throwingParts.contains(part) && (currentThrowStates.contains(ts) || ts.state != 1)) { - GraphPart t = ts.targetPart; - if (!visited.contains(t)) { - getLoopsWalk(localData, t, loops, throwStates, stopPart, false, visited, level + 1 /*???*/); - } - } - } - for (Loop l : loops2) { + }*/ + /*for (Loop l : loops2) { l.breakCandidatesLocked--; - } - + }*/ if (isLoop && currentLoop != null) { GraphPart found; @@ -1386,7 +1393,7 @@ public class Graph { findPartsOutsideTry(ts, cand, outsideTry, new HashSet<>()); for (int j = outsideTry.size() - 1; j >= 0; j--) { - if (!canBeBreakCandidate(localData, outsideTry.get(j))) { + if (!canBeBreakCandidate(localData, outsideTry.get(j), throwStates)) { outsideTry.remove(j); } } @@ -1463,7 +1470,7 @@ public class Graph { currentLoop.breakCandidates.add(other); currentLoop.breakCandidatesLevels.add(curLev); - + break loopcand; } } @@ -1486,7 +1493,7 @@ public class Graph { removed.put(found, maxlevel); } } while ((found != null) && (currentLoop.breakCandidates.size() > 1)); - + Map count = new HashMap<>(); GraphPart winner = null; int winnerCount = 0; @@ -2082,7 +2089,7 @@ public class Graph { GraphTargetItem leftSide = expr.getNotCoercedNoDup(); boolean hideEmptyTrueFalse = true; - + if (leftSide instanceof DuplicateItem) { isIf = false; if (hideEmptyTrueFalse && prevExpr.getNotCoercedNoDup() instanceof FalseItem) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ThrowState.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ThrowState.java index b353b2faf..908e21ee0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ThrowState.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/ThrowState.java @@ -13,6 +13,7 @@ public class ThrowState { public Set throwingParts = new HashSet<>(); public GraphPart targetPart; + public Set catchParts = new HashSet<>(); @Override public int hashCode() { 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 5ce92bb74..d1c84c8f1 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 @@ -230,6 +230,35 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT false); } + @Test + public void testTryCatchLoopBreakLevel2() { + decompileMethod("assembled", "testTryCatchLoopBreakLevel2", "var a:int = 0;\r\n" + + "a = 0;\r\n" + + "trace(\"before loop\");\r\n" + + "loop0:\r\n" + + "while(true)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch1\");\r\n" + + "while(a <= 5)\r\n" + + "{\r\n" + + "if(a > 5)\r\n" + + "{\r\n" + + "break loop0;\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"in catch1c\");\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + @Test public void testTryDoWhile() { decompileMethod("assembled", "testTryDoWhile", "trace(\"first\");\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileDecompileTest.java index a8d265996..0e45c83c7 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileDecompileTest.java @@ -311,6 +311,124 @@ public class ActionScript3CrossCompileDecompileTest extends ActionScript3Decompi false); } + @Test(dataProvider = "swfNamesProvider") + public void testTryCatchLoopBreak2(String swfUsed) { + decompileMethod(swfUsed, "testTryCatchLoopBreak2", "var a:int = 0;\r\n" + + "a = 0;\r\n" + + "trace(\"before loop\");\r\n" + + "while(a < 20)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "return;\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch\");\r\n" + + "trace(\"a=\" + a);\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryCatchLoopBreak3(String swfUsed) { + decompileMethod(swfUsed, "testTryCatchLoopBreak3", "var a:int = 0;\r\n" + + "a = 0;\r\n" + + "trace(\"before loop\");\r\n" + + "while(true)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch1\");\r\n" + + "break;\r\n" + + "}\r\n" + + "catch(e:EOFError)\r\n" + + "{\r\n" + + "trace(\"in catch2\");\r\n" + + "break;\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryCatchLoopBreak4(String swfUsed) { + decompileMethod(swfUsed, "testTryCatchLoopBreak4", "var a:int = 0;\r\n" + + "a = 0;\r\n" + + "trace(\"before loop\");\r\n" + + "while(true)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch1\");\r\n" + + "if(a > 5)\r\n" + + "{\r\n" + + "trace(\"a\");\r\n" + + "if(a > 6)\r\n" + + "{\r\n" + + "trace(\"b\");\r\n" + + "break;\r\n" + + "}\r\n" + + "trace(\"c\");\r\n" + + "}\r\n" + + "trace(\"in catch1b\");\r\n" + + "if(a > 10)\r\n" + + "{\r\n" + + "trace(\"d\");\r\n" + + "if(a > 11)\r\n" + + "{\r\n" + + "trace(\"e\");\r\n" + + "break;\r\n" + + "}\r\n" + + "trace(\"f\");\r\n" + + "}\r\n" + + "trace(\"in catch1c\");\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + + @Test(dataProvider = "swfNamesProvider") + public void testTryCatchLoopBreak5(String swfUsed) { + decompileMethod(swfUsed, "testTryCatchLoopBreak5", "var a:int = 0;\r\n" + + "a = 0;\r\n" + + "trace(\"before loop\");\r\n" + + "while(true)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch1\");\r\n" + + "while(true)\r\n" + + "{\r\n" + + "if(a > 5)\r\n" + + "{\r\n" + + "break;\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"in catch1c\");\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + @Test(dataProvider = "swfNamesProvider") public void testTryCatchTry(String swfUsed) { decompileMethod(swfUsed, "testTryCatchTry", "trace(\"before try\");\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java index 99a721e4e..2f8ef49e0 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3CrossCompileSwfToolsDecompileTest.java @@ -350,6 +350,76 @@ public class ActionScript3CrossCompileSwfToolsDecompileTest extends ActionScript false); } + @Test + public void testTryCatchLoopBreak4() { + decompileMethod("swftools", "testTryCatchLoopBreak4", "var _loc1_:int = 0;\r\n" + + "_loc1_ = 0;\r\n" + + "trace(\"before loop\");\r\n" + + "while(true)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch1\");\r\n" + + "if(_loc1_ > 5)\r\n" + + "{\r\n" + + "trace(\"a\");\r\n" + + "if(_loc1_ > 6)\r\n" + + "{\r\n" + + "trace(\"b\");\r\n" + + "break;\r\n" + + "}\r\n" + + "trace(\"c\");\r\n" + + "}\r\n" + + "trace(\"in catch1b\");\r\n" + + "if(_loc1_ > 10)\r\n" + + "{\r\n" + + "trace(\"d\");\r\n" + + "if(_loc1_ > 11)\r\n" + + "{\r\n" + + "trace(\"e\");\r\n" + + "break;\r\n" + + "}\r\n" + + "trace(\"f\");\r\n" + + "}\r\n" + + "trace(\"in catch1c\");\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + + @Test + public void testTryCatchLoopBreak5() { + decompileMethod("swftools", "testTryCatchLoopBreak5", "var _loc1_:int = 0;\r\n" + + "_loc1_ = 0;\r\n" + + "trace(\"before loop\");\r\n" + + "while(true)\r\n" + + "{\r\n" + + "try\r\n" + + "{\r\n" + + "trace(\"in try\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"in catch1\");\r\n" + + "while(true)\r\n" + + "{\r\n" + + "if(_loc1_ > 5)\r\n" + + "{\r\n" + + "break;\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"in catch1c\");\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"after\");\r\n", + false); + } + @Test public void testTryCatchTry() { decompileMethod("swftools", "testTryCatchTry", "trace(\"before try\");\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 26f49143f..f6d2e4bc8 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 f462f3840..18c2a11f1 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 @@ -22,5 +22,6 @@ program #include "tests/TestSwitchJoin.script.asasm" #include "tests/TestDeobfuscatorJumpsExceptionStart.script.asasm" #include "tests/TestUnnamedException.script.asasm" + #include "tests/TestTryCatchLoopBreakLevel2.script.asasm" ; place to add next end ; program diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestTryCatchLoopBreakLevel2.class.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestTryCatchLoopBreakLevel2.class.asasm new file mode 100644 index 000000000..517dc0bfa --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestTryCatchLoopBreakLevel2.class.asasm @@ -0,0 +1,139 @@ +class + refid "tests:TestTryCatchLoopBreakLevel2" + instance QName(PackageNamespace("tests"), "TestTryCatchLoopBreakLevel2") + extends QName(PackageNamespace(""), "Object") + flag SEALED + flag PROTECTEDNS + protectedns ProtectedNamespace("tests:TestTryCatchLoopBreakLevel2") + iinit + refid "tests:TestTryCatchLoopBreakLevel2/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:TestTryCatchLoopBreakLevel2/instance/run" + returns QName(PackageNamespace(""), "void") + body + maxstack 4 + localcount 4 + initscopedepth 0 + maxscopedepth 2 + + code + getlocal0 + pushscope + debug 1, "a", 0, 0 + pushbyte 0 + setlocal1 + debugline 15 + pushbyte 0 + setlocal1 + getlex QName(PackageNamespace(""),"trace") + getglobalscope + debugline 16 + pushstring "before loop" + call 1 + pop + debugline 17 + label + jump ofs007d + ofs0023: + label + ofs0024: + getlex QName(PackageNamespace(""),"trace") + getglobalscope + debugline 21 + pushstring "in try" + call 1 + pop + debugline 19 + ofs0030: + jump ofs007d + ofs0034: + getlocal0 + pushscope + newcatch 0 + dup + setlocal3 + dup + pushscope + swap + setslot 1 + getlex QName(PackageNamespace(""),"trace") + getglobalscope + debugline 25 + pushstring "in catch1" + call 1 + pop + label + jump ofs006b + ofs004f: + label + getlocal1 + debugline 27 + pushbyte 5 + ifgt ofs006f + getlocal1 + debugline 30 + pushbyte 5 + ifngt ofs006b + popscope + kill 3 + jump ofs0081 + debugline 26 + ofs006b: + jump ofs004f + ofs006f: + getlex QName(PackageNamespace(""),"trace") + getglobalscope + debugline 34 + pushstring "in catch1c" + call 1 + pop + popscope + debugline 18 + ofs007d: + jump ofs0023 + ofs0081: + getlex QName(PackageNamespace(""),"trace") + getglobalscope + debugline 37 + pushstring "after" + call 1 + returnvoid + end ; code + try from ofs0024 to ofs0030 target ofs0034 type QName(PackageNamespace(""),"Error") name QName(PackageInternalNs("tests"),"e") end + end ; body + end ; method + end ; trait + end ; instance + cinit + refid "tests:TestTryCatchLoopBreakLevel2/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/TestTryCatchLoopBreakLevel2.script.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestTryCatchLoopBreakLevel2.script.asasm new file mode 100644 index 000000000..0e02f73ba --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestTryCatchLoopBreakLevel2.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestTryCatchLoopBreakLevel2/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestTryCatchLoopBreakLevel2", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestTryCatchLoopBreakLevel2"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestTryCatchLoopBreakLevel2" + popscope + initproperty QName(PackageNamespace("tests"), "TestTryCatchLoopBreakLevel2") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestTryCatchLoopBreakLevel2") + #include "TestTryCatchLoopBreakLevel2.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 f59877f9b..37e48f0b2 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 diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/as3_cross_compile.as3proj b/libsrc/ffdec_lib/testdata/as3_cross_compile/as3_cross_compile.as3proj index 229ddda42..00961f79f 100644 --- a/libsrc/ffdec_lib/testdata/as3_cross_compile/as3_cross_compile.as3proj +++ b/libsrc/ffdec_lib/testdata/as3_cross_compile/as3_cross_compile.as3proj @@ -12,6 +12,7 @@ + diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.air.swf b/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.air.swf index 3e4182248..4cd8e972c 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.air.swf and b/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.air.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.flex.swf b/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.flex.swf index 0e8ab6c1d..68b0b74c8 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.flex.swf and b/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.flex.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.flex_apache.swf b/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.flex_apache.swf index 21cba0c23..e52eecae3 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.flex_apache.swf and b/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.flex_apache.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.swftools.swf b/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.swftools.swf index 4ed63e071..ec2d88478 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.swftools.swf and b/libsrc/ffdec_lib/testdata/as3_cross_compile/bin/as3_cross_compile.swftools.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/build_air_debug.bat b/libsrc/ffdec_lib/testdata/as3_cross_compile/build_air_debug.bat index 35668d86d..248c9259b 100644 --- a/libsrc/ffdec_lib/testdata/as3_cross_compile/build_air_debug.bat +++ b/libsrc/ffdec_lib/testdata/as3_cross_compile/build_air_debug.bat @@ -1,4 +1,6 @@ @echo off set COMPILERKIND=air set SWFNAME=as3_cross_compile -call c:\air\bin\mxmlc.bat -warnings=false -debug=true -output bin/%SWFNAME%.%COMPILERKIND%.swf src/Main.as 1> buildlog.%COMPILERKIND%.txt 2>&1 \ No newline at end of file +call c:\air\bin\mxmlc.bat -warnings=false -debug=true -output bin/%SWFNAME%.%COMPILERKIND%.swf src/Main.as 1> buildlog.%COMPILERKIND%.txt 2>&1 +IF NOT ERRORLEVEL 0 echo "FAILED" +exit /b 0 \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/build_flex_apache_debug.bat b/libsrc/ffdec_lib/testdata/as3_cross_compile/build_flex_apache_debug.bat index 9254f2700..65d230c89 100644 --- a/libsrc/ffdec_lib/testdata/as3_cross_compile/build_flex_apache_debug.bat +++ b/libsrc/ffdec_lib/testdata/as3_cross_compile/build_flex_apache_debug.bat @@ -1,4 +1,6 @@ @echo off set COMPILERKIND=flex_apache set SWFNAME=as3_cross_compile -call c:\flex_apache\bin\mxmlc.bat -warnings=false -debug=true -output bin/%SWFNAME%.%COMPILERKIND%.swf src/Main.as 1> buildlog.%COMPILERKIND%.txt 2>&1 \ No newline at end of file +call c:\flex_apache\bin\mxmlc.bat -warnings=false -debug=true -output bin/%SWFNAME%.%COMPILERKIND%.swf src/Main.as 1> buildlog.%COMPILERKIND%.txt 2>&1 +IF NOT ERRORLEVEL 0 echo "FAILED" +exit /b 0 \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/build_flex_debug.bat b/libsrc/ffdec_lib/testdata/as3_cross_compile/build_flex_debug.bat index ef39749a8..e28a2256f 100644 --- a/libsrc/ffdec_lib/testdata/as3_cross_compile/build_flex_debug.bat +++ b/libsrc/ffdec_lib/testdata/as3_cross_compile/build_flex_debug.bat @@ -1,4 +1,6 @@ @echo off set COMPILERKIND=flex set SWFNAME=as3_cross_compile -c:\flex\bin\mxmlc.exe -warnings=false -debug=true -output bin/%SWFNAME%.%COMPILERKIND%.swf src/Main.as 1> buildlog.%COMPILERKIND%.txt 2>&1 \ No newline at end of file +c:\flex\bin\mxmlc.exe -warnings=false -debug=true -output bin/%SWFNAME%.%COMPILERKIND%.swf src/Main.as 1> buildlog.%COMPILERKIND%.txt 2>&1 +IF NOT ERRORLEVEL 0 echo "FAILED" +exit /b 0 \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/build_swftools_debug.bat b/libsrc/ffdec_lib/testdata/as3_cross_compile/build_swftools_debug.bat index 0330fc2fe..10c8a732d 100644 --- a/libsrc/ffdec_lib/testdata/as3_cross_compile/build_swftools_debug.bat +++ b/libsrc/ffdec_lib/testdata/as3_cross_compile/build_swftools_debug.bat @@ -2,4 +2,6 @@ set COMPILERKIND=swftools set SWFNAME=as3_cross_compile cd src -c:\swftools\as3compile.exe Main.as -o ..\bin\%SWFNAME%.%COMPILERKIND%.swf 1> ../buildlog.%COMPILERKIND%.txt 2>&1 \ No newline at end of file +c:\swftools\as3compile.exe Main.as -o ..\bin\%SWFNAME%.%COMPILERKIND%.swf 1> ../buildlog.%COMPILERKIND%.txt 2>&1 +IF NOT ERRORLEVEL 0 echo "FAILED" +exit /b 0 \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/obj/as3_cross_compileConfig.old b/libsrc/ffdec_lib/testdata/as3_cross_compile/obj/as3_cross_compileConfig.old index 1660079f7..6d522439f 100644 --- a/libsrc/ffdec_lib/testdata/as3_cross_compile/obj/as3_cross_compileConfig.old +++ b/libsrc/ffdec_lib/testdata/as3_cross_compile/obj/as3_cross_compileConfig.old @@ -3,8 +3,6 @@ 25.0 - false - true CONFIG::debug @@ -16,7 +14,7 @@ CONFIG::timeStamp - '08.02.2021' + '09.02.2021' CONFIG::air diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/obj/as3_cross_compileConfig.xml b/libsrc/ffdec_lib/testdata/as3_cross_compile/obj/as3_cross_compileConfig.xml index 1660079f7..8bd4a91f5 100644 --- a/libsrc/ffdec_lib/testdata/as3_cross_compile/obj/as3_cross_compileConfig.xml +++ b/libsrc/ffdec_lib/testdata/as3_cross_compile/obj/as3_cross_compileConfig.xml @@ -16,7 +16,7 @@ CONFIG::timeStamp - '08.02.2021' + '09.02.2021' CONFIG::air diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/src/Main.as b/libsrc/ffdec_lib/testdata/as3_cross_compile/src/Main.as index c27286af8..db5b45843 100644 --- a/libsrc/ffdec_lib/testdata/as3_cross_compile/src/Main.as +++ b/libsrc/ffdec_lib/testdata/as3_cross_compile/src/Main.as @@ -21,6 +21,10 @@ package TestTryCatchInWhile5; TestTryCatchLoop; TestTryCatchLoopBreak; + TestTryCatchLoopBreak2; + TestTryCatchLoopBreak3; + TestTryCatchLoopBreak4; + TestTryCatchLoopBreak5; TestTryCatchExceptionUsage TestTryFinally; TestTryFinallyDirectReturnInFinally; diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/src/tests/TestTryCatchLoopBreak4.as b/libsrc/ffdec_lib/testdata/as3_cross_compile/src/tests/TestTryCatchLoopBreak4.as new file mode 100644 index 000000000..b0b6a3f36 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_cross_compile/src/tests/TestTryCatchLoopBreak4.as @@ -0,0 +1,51 @@ +package tests +{ + import flash.errors.EOFError; + /** + * ... + * @author JPEXS + */ + public class TestTryCatchLoopBreak4 + { + + + public function run() : void + { + var a:int; + a = 0; + trace("before loop"); + while (true) { + try + { + trace("in try"); + } + catch(e:Error) + { + trace("in catch1"); + if (a > 5){ + trace("a"); + if (a > 6){ + trace("b"); + break; + } + trace("c"); + } + trace("in catch1b"); + if (a > 10){ + trace("d"); + if (a > 11){ + trace("e"); + break; + } + trace("f"); + } + trace("in catch1c"); + } + } + trace("after"); + + } + + } + +} \ No newline at end of file diff --git a/libsrc/ffdec_lib/testdata/as3_cross_compile/src/tests/TestTryCatchLoopBreak5.as b/libsrc/ffdec_lib/testdata/as3_cross_compile/src/tests/TestTryCatchLoopBreak5.as new file mode 100644 index 000000000..14e6cdd33 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_cross_compile/src/tests/TestTryCatchLoopBreak5.as @@ -0,0 +1,39 @@ +package tests +{ + import flash.errors.EOFError; + /** + * ... + * @author JPEXS + */ + public class TestTryCatchLoopBreak5 + { + + + public function run() : void + { + var a:int; + a = 0; + trace("before loop"); + while (true) { + try + { + trace("in try"); + } + catch(e:Error) + { + trace("in catch1"); + while (true){ + if (a > 5){ + break; + } + } + trace("in catch1c"); + } + } + trace("after"); + + } + + } + +} \ No newline at end of file