diff --git a/CHANGELOG.md b/CHANGELOG.md index 5df4ec8e4..087f8bbc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ All notable changes to this project will be documented in this file. - [#1668] Not removing SymbolClass/ExportAssets entry on character remove - [#1670] Parent component/window of dialogs not properly set - AS decompilation - Gotos handling vs and/or +- AS decompilation - certain combinations of ifs and switch ## [14.3.1] - 2021-03-25 ### Fixed 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 535a89634..a7f6c86c5 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/Graph.java @@ -1963,6 +1963,7 @@ public class Graph { if (stopPart.contains(part)) { boolean hasBlockClosesAfter = false; + //this weird stuff handles some goto problems: loopi: for (int i = 0; i < stopPartKind.size(); i++) { if (stopPart.get(i) == part) { @@ -2294,8 +2295,10 @@ public class Graph { List stopPartKind2 = new ArrayList<>(stopPartKind); if ((!isEmpty) && (next != null)) { - stopPart2.add(next); - stopPartKind2.add(StopPartKind.BLOCK_CLOSE); + if (!stopPart2.contains(next)) { //?? might be a break or something + stopPart2.add(next); + stopPartKind2.add(StopPartKind.BLOCK_CLOSE); + } } List onTrue = new ArrayList<>(); 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 158c52711..b02623e6f 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 @@ -190,6 +190,34 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT false); } + @Test + public void testSwitchGoto() { + decompileMethod("assembled", "testSwitchGoto", "var i:int = 5;\r\n" + + "var a:Boolean = true;\r\n" + + "var b:Boolean = false;\r\n" + + "switch(i)\r\n" + + "{\r\n" + + "case 0:\r\n" + + "trace(\"case0\");\r\n" + + "break;\r\n" + + "case 1:\r\n" + + "if(a)\r\n" + + "{\r\n" + + "if(b)\r\n" + + "{\r\n" + + "trace(\"a\");\r\n" + + "}\r\n" + + "break;\r\n" + + "}\r\n" + + "trace(\"b\");\r\n" + + "trace(\"c\");\r\n" + + "break;\r\n" + + "case 2:\r\n" + + "trace(\"case2\");\r\n" + + "}\r\n", + false); + } + @Test public void testSwitchJoin() { decompileMethod("assembled", "testSwitchJoin", "trace(\"before\");\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 abe150dee..930971d3a 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 3eed3fd5d..3d6b3666a 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 @@ -26,5 +26,6 @@ program #include "tests/TestSlots.script.asasm" #include "tests/TestSlots.init/inline_method.method.asasm" #include "tests/TestDecrementPrecedence.script.asasm" + #include "tests/TestSwitchGoto.script.asasm" ; place to add next end ; program diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestSwitchGoto.class.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestSwitchGoto.class.asasm new file mode 100644 index 000000000..489822dc6 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestSwitchGoto.class.asasm @@ -0,0 +1,195 @@ +class + refid "tests:TestSwitchGoto" + instance QName(PackageNamespace("tests"), "TestSwitchGoto") + extends QName(PackageNamespace(""), "Object") + flag SEALED + flag PROTECTEDNS + protectedns ProtectedNamespace("tests:TestSwitchGoto") + iinit + refid "tests:TestSwitchGoto/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:TestSwitchGoto/instance/run" + returns QName(PackageNamespace(""), "void") + body + maxstack 2 + localcount 4 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + + getlocal0 + pushscope + + debug 1, "i", 0, 8 + debug 1, "a", 1, 9 + debug 1, "b", 2, 10 + + pushbyte 5 + convert_i + setlocal1 + + + pushtrue + convert_b + setlocal2 + + + pushfalse + convert_b + setlocal3 + + jump L66 + +L20: + label + + findpropstrict QName(PackageNamespace(""), "trace") + pushstring "case0" + callproperty QName(PackageNamespace(""), "trace"), 1 + pop + + jump L94 + +L28: + label + + getlocal2 + iffalse L44 + + + getlocal3 + not + iftrue L94 + jump L38 + ;iffalse L38 + + + ;jump L94 +;LXX: +; jump L94 +L38: + + findpropstrict QName(PackageNamespace(""), "trace") + pushstring "a" + callproperty QName(PackageNamespace(""), "trace"), 1 + pop + jump L49 + +L44: + + findpropstrict QName(PackageNamespace(""), "trace") + pushstring "b" + callproperty QName(PackageNamespace(""), "trace"), 1 + pop +L49: +; 40-44 + findpropstrict QName(PackageNamespace(""), "trace") + pushstring "c" + callproperty QName(PackageNamespace(""), "trace"), 1 + pop + + jump L94 + +L56: + label + + findpropstrict QName(PackageNamespace(""), "trace") + pushstring "case2" + callproperty QName(PackageNamespace(""), "trace"), 1 + pop + + jump L94 + +L64: + label + jump L94 + +L66: + + getlocal1 + setlocal 4 + + + pushbyte 0 + getlocal 4 + ifstrictne L75 + + pushshort 0 + jump L92 + +L75: + + pushbyte 1 + getlocal 4 + ifstrictne L81 + + pushshort 1 + jump L92 + +L81: + + pushbyte 2 + getlocal 4 + ifstrictne L87 + + pushshort 2 + jump L92 + +L87: + pushfalse + iffalse L91 + + pushshort 3 + jump L92 + +L91: + pushshort 3 +L92: + kill 4 + lookupswitch L64, [L20, L28, L56, L64] + +L94: + + returnvoid + + returnvoid + end ; code + end ; body + end ; method + end ; trait + end ; instance + cinit + refid "tests:TestSwitchGoto/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/TestSwitchGoto.script.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestSwitchGoto.script.asasm new file mode 100644 index 000000000..21e630638 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestSwitchGoto.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestSwitchGoto/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestSwitchGoto", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestSwitchGoto"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestSwitchGoto" + popscope + initproperty QName(PackageNamespace("tests"), "TestSwitchGoto") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestSwitchGoto") + #include "TestSwitchGoto.class.asasm" + end ; trait +end ; script