diff --git a/CHANGELOG.md b/CHANGELOG.md index 344eef55e..3b2944e1d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ All notable changes to this project will be documented in this file. - [#2338] AS1/2/3 Obfuscated code - jump to jump handling - [#1277] AS1/2 Propagate break/continue to avoid loop/switch labels - [#2483] Editing shape gradient records - RGB vs RGBA +- [#2486] AS Loop in loop producing gotos in some cases ### Changed - Icon of "Deobfuscation options" menu from pile of pills to medkit @@ -3917,6 +3918,7 @@ Major version of SWF to XML export changed to 2. [#2338]: https://www.free-decompiler.com/flash/issues/2338 [#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 [#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/graph/Graph.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java index bb601d5bc..a9634eb24 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -111,19 +111,19 @@ public class Graph { /** * Debug flag to print all parts */ - private boolean debugPrintAllParts = false; + private final boolean debugPrintAllParts = false; /** * Debug flag to print loop list */ - private boolean debugPrintLoopList = false; + private final boolean debugPrintLoopList = false; /** * Debug flag to print getLoops */ - private boolean debugGetLoops = false; + private final boolean debugGetLoops = false; /** * Debug flag to print decompilation progress (printGraph method) */ - private boolean debugPrintGraph = false; + private final boolean debugPrintGraph = false; /** * Debug flag to not process Ifs */ @@ -1600,7 +1600,14 @@ public class Graph { for (Loop el : loops) { el.backEdges.clear(); Set uniqueRefs = new HashSet<>(el.loopContinue.refs); - for (GraphPart r : uniqueRefs) { + loopr: for (GraphPart r : uniqueRefs) { + for (Loop el2 : loops) { + if (el2.phase == 1) { + if (el2.loopContinue == r) { + continue loopr; + } + } + } if (el.loopContinue.leadsTo(localData, this, code, r, loops, throwStates, true)) { el.backEdges.add(r); } @@ -3208,7 +3215,7 @@ public class Graph { if (stopPart.get(i) == part) { isRealStopPart = true; } - break; + break; } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java index 05ddcc313..b9bc90b3f 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java @@ -1500,6 +1500,44 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile false); } + @Test + public void testLoopInLoop() { + decompileMethod("classic_air", "testLoopInLoop", "var i:* = undefined;\r\n" + + "var a:Boolean = true;\r\n" + + "var b:Boolean = true;\r\n" + + "var c:Boolean = true;\r\n" + + "do\r\n" + + "{\r\n" + + "trace(\"A\");\r\n" + + "for(i = 0; i < 10; i++)\r\n" + + "{\r\n" + + "if(!a)\r\n" + + "{\r\n" + + "trace(\"B\");\r\n" + + "if(c)\r\n" + + "{\r\n" + + "trace(\"C\");\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"D\");\r\n" + + "if(b)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"H\");\r\n" + + "}\r\n" + + "if(c)\r\n" + + "{\r\n" + + "trace(\"L\");\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "while(!a);\r\n", + false); + } + @Test public void testManualConvert() { decompileMethod("classic_air", "testManualConvert", "trace(\"String(this).length\");\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java index 23047d678..ab3927748 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java @@ -1496,6 +1496,46 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes false); } + @Test + public void testLoopInLoop() { + decompileMethod("classic", "testLoopInLoop", "var i:* = undefined;\r\n" + + "var a:Boolean = true;\r\n" + + "var b:Boolean = true;\r\n" + + "for(var c:Boolean = true; true; )\r\n" + + "{\r\n" + + "trace(\"A\");\r\n" + + "for(i = 0; i < 10; i++)\r\n" + + "{\r\n" + + "if(!a)\r\n" + + "{\r\n" + + "trace(\"B\");\r\n" + + "if(c)\r\n" + + "{\r\n" + + "trace(\"C\");\r\n" + + "}\r\n" + + "else\r\n" + + "{\r\n" + + "trace(\"D\");\r\n" + + "if(b)\r\n" + + "{\r\n" + + "continue;\r\n" + + "}\r\n" + + "trace(\"H\");\r\n" + + "}\r\n" + + "if(c)\r\n" + + "{\r\n" + + "trace(\"L\");\r\n" + + "}\r\n" + + "}\r\n" + + "}\r\n" + + "if(a)\r\n" + + "{\r\n" + + "break;\r\n" + + "}\r\n" + + "}\r\n", + false); + } + @Test public void testManualConvert() { decompileMethod("classic", "testManualConvert", "trace(\"String(this).length\");\r\n" diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf index de76fe8d2..cbf1d8cea 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf index bd22e2914..896b2943c 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as index 3101b597c..217bd3476 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as +++ b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as @@ -88,6 +88,7 @@ package TestInnerFunctionScope; TestInnerIf; TestInnerTry; + TestLoopInLoop; TestLogicalComputing; TestManualConvert; TestMetadata; diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestLoopInLoop.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestLoopInLoop.as new file mode 100644 index 000000000..77f3a0916 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestLoopInLoop.as @@ -0,0 +1,54 @@ +package tests +{ + + public class TestLoopInLoop + { + public function run():* + { + var a:Boolean = true; + var b:Boolean = true; + var c:Boolean = true; + + + for (;;) + { + trace("A"); + + for (var i = 0; i < 10; i++) + { + if (a) + { + continue; + } + + trace("B"); + if (c) + { + trace("C"); + } + else + { + trace("D"); + if (b) + { + continue; + } + + trace("H"); + + } + + if (c) + { + trace("L"); + } + } + + if (a) + { + break; + } + } + } + } +}