diff --git a/CHANGELOG.md b/CHANGELOG.md index d9f7c7867..f1f85185e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ All notable changes to this project will be documented in this file. ### Added - [#2221] AS3 P-code - add new function button (creates methodinfo, methodbody) +### Fixed +- [#2267] Script decompilation - Loop detection causing `§§goto` instructions in some cases + ## [21.0.0] - 2024-08-05 ### Added - StartSound and StartSound2 show characterId/class in the tag tree 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 099fd72ce..794d0fb46 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -2949,6 +2949,14 @@ public class Graph { List stopPartKind2 = new ArrayList<>(stopPartKind); stopPartKind2.add(StopPartKind.OTHER); Set subVisited = new HashSet<>(); + + /* + * Save loop phases to be able to walk precontinue block again. + */ + List loopPhases = new ArrayList<>(); + for (Loop el : loops) { + loopPhases.add(el.phase); + } precontinueCommands = printGraph(foundGotos, partCodes, partCodePos, subVisited, localData, new TranslateStack(path), allParts, null, backup, stopPart2, stopPartKind2, loops, throwStates, null, staticOperation, path, recursionLevel + 1); currentLoop.loopPreContinue = backup; checkContinueAtTheEnd(precontinueCommands, currentLoop); @@ -2980,6 +2988,13 @@ public class Graph { } if (currentLoop.loopPreContinue == null) { precontinueCommands.clear(); + + /** + * Restore loop phases + */ + for (int i = 0; i < loopPhases.size(); i++) { + loops.get(i).phase = loopPhases.get(i); + } } } } 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 fdbf0e233..1253e43c3 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 @@ -2226,6 +2226,25 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile false); } + @Test + public void testWhileDoWhile() { + decompileMethod("classic_air", "testWhileDoWhile", "trace(\"A\");\r\n" + + "var i:int = 0;\r\n" + + "while(i < 10)\r\n" + + "{\r\n" + + "trace(\"B\");\r\n" + + "do\r\n" + + "{\r\n" + + "i++;\r\n" + + "trace(\"C\");\r\n" + + "}\r\n" + + "while(i < 5);\r\n" + + "\r\n" + + "}\r\n" + + "trace(\"E\");\r\n", + false); + } + @Test public void testWhileSwitch() { decompileMethod("classic_air", "testWhileSwitch", "var a:Boolean = true;\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 c872c4f6e..646e40a5a 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 @@ -2219,6 +2219,25 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes false); } + @Test + public void testWhileDoWhile() { + decompileMethod("classic", "testWhileDoWhile", "trace(\"A\");\r\n" + + "var i:int = 0;\r\n" + + "while(i < 10)\r\n" + + "{\r\n" + + "trace(\"B\");\r\n" + + "do\r\n" + + "{\r\n" + + "i++;\r\n" + + "trace(\"C\");\r\n" + + "}\r\n" + + "while(i < 5);\r\n" + + "\r\n" + + "}\r\n" + + "trace(\"E\");\r\n", + false); + } + @Test public void testWhileSwitch() { decompileMethod("classic", "testWhileSwitch", "var a:Boolean = true;\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 44b78f804..ed73ce35a 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 44c253532..ca08b6cb4 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 21a4e0d21..aa885d3d9 100644 --- a/libsrc/ffdec_lib/testdata/as3_new/src/Main.as +++ b/libsrc/ffdec_lib/testdata/as3_new/src/Main.as @@ -130,6 +130,7 @@ package TestWhileBreak; TestWhileBreak2; TestWhileContinue; + TestWhileDoWhile; TestWhileSwitch; TestWhileTry; TestWhileTry2; diff --git a/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestWhileDoWhile.as b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestWhileDoWhile.as new file mode 100644 index 000000000..db2fe91ee --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_new/src/tests/TestWhileDoWhile.as @@ -0,0 +1,24 @@ +package tests +{ + + public class TestWhileDoWhile + { + public function run():* + { + trace("A"); + var i:int = 0; + + while (i < 10) + { + trace("B"); + do + { + i++; + trace("C"); + } while (i < 5); + } + trace("E"); + + } + } +}