From b7e418f6b6775b6e47d0fb2566e2f82ddf344fa6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 27 Mar 2021 19:14:41 +0100 Subject: [PATCH] Fixed: AS decompilation - certain combinations of ifs and switch --- CHANGELOG.md | 1 + .../src/com/jpexs/decompiler/graph/Graph.java | 7 +- .../ActionScript3AssembledDecompileTest.java | 28 +++ .../as3_assembled-0/as3_assembled-0.main.abc | Bin 6084 -> 6444 bytes .../as3_assembled-0.main.asasm | 1 + .../tests/TestSwitchGoto.class.asasm | 195 ++++++++++++++++++ .../tests/TestSwitchGoto.script.asasm | 29 +++ 7 files changed, 259 insertions(+), 2 deletions(-) create mode 100644 libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestSwitchGoto.class.asasm create mode 100644 libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestSwitchGoto.script.asasm 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 abe150dee6bf8b5af120a454e4f09ff2a5924dd7..930971d3ad8c7920e1f3e440ef40649ae297de70 100644 GIT binary patch delta 2202 zcmXw(OK=;<5r(@5yE{7|2rNP35s(mHAV2_1aQP4^i{eY90O|?71yLde0s>6gq9~D) zY)eTf%a-Gu;$*5)NgUfMS8{PVaV5&#m5MK^%7Kz&=8{vYT**z$H5a6ZFo2rvZ~E`) z?Ro5cHTe0kX+Z|)_w=XcyFpyhSE_d_8^-4PTIJTJc5>y$EiC=v<8IV)>vz}XpYYnV z0K0?TMyXO=->5XzP1nu!_1jq1%PX4|XYV=u>_b-u8QysIS8agR2Y+k4pUwu|LC0JR zIl*f>(0@Va!RsM+$PSx2goh$#q!?L=lp^IwMLy--@(b?v*d`BFgFN&ehPnJFPX)ri z!0<0I{3{H9h~Zyj_#=!AwM$`+;t@GzZj98%TszCPxO^%mb&Lp~OMWZH zJ9<#`qKKh*AK5av5^6j5e&||wHt3#4cVE5lN`oAA$F?{_*M4ea)DBR4h1x-Chp0`3 zn$w~g7>**i+L-Wxff@o2F>wIg3Y!8nRo?)3PTYlCLp4)y`70e zuuoy9pNUcEA>4xA?=f)@;>w+9Wnw?16sGqvF$EcggHa|XVOZgakBK1|Q#jtk#9=t7 zaH5xqIhay7-NnQV99B5j!o&z<73N}0%)>E-$Ge%Bg;NUi9Sk9J&NVfI`UcY28K!R{ z;^ZuxN6n&rgG(x|(8a209EX5lRA7hw@Xa@TV)+oOSZ z275K|&107a)&jO@&~gG}8u(9Rw+5{jw2paK8yXx?2NReMakVR#(b6EWgq<1$m*soS z<7XcFO@QruA6OoMrJ6VfT@(XXpxT)~6 zjQBF){bg?X0Yr(H%-%=GQ)T1%i;|unmqlNjv8Lk6@_}z6l*wlxN9n?ibn8kxC;#Rf zPTTfYNl!iUK2NV<{xB=r`8mh|o&fX$ZB4zhJ1YLXOj-l&0~EIaIAD<8)zCMTensA~ zQpr?F&!+Ivu~e$;uFii@a#s(1ke^XY5^F@?P|-#Cm1T#L_vA{FwEl*6TWKZ9Tjq_| z6ke2PS{@pA6)wvcEvdP&&32oXw~b~4K-5Kp2~O|i?4~C>YJ+SKS&eM-lO5aGq3olL z?3*gjH974c@3@&qjM79;0v-VRp!)c)kH_bDH|jw)d;i=GC8zt#}Gi@Z$0swD)H%pH@ey*L#^pde-<%W!KFks zk)4IdYq&(|mCvGSZ9C7MMM&+W99nD=lJa(ITij4`4kJBrL*OYufSE@2w^a5E1z&Wv zSAN#of8jipV4bfQJ)*c7_a-o^_pZUb&vl+w{QEjD$wb?4vrXio zIeO}*xo&3bX1;E6b#s(V*8;$NqsaTJ$i;#cUG0+ofQ@g-=|CJG$ZBBBSXJ7J{50TT zzx+DT-Sj{?t`_{!)tIaW5;2|54}7!hqel_1?^^bSSxoM>2&+KVDNn$@Baa0mxGpQf zjB}gR=&s-TO|7QHKHHe3J?S18GV*Y`QP3Oe9ZQAQ=xVq8OYjpb{$Fi3Zoj(B(<^*8 zVXw-K(EQe`D(F%n5M8zCBrVc*YOZaEknSE$H@2Paqx8MNRiW6%3UgUZJx#6s%UaEK fuU30ptNpQ7qmH^GmKv*bPfh%~SqMf~JIVil`hk&N delta 1866 zcmXw&OHfm16vxl`l6%kn0!c1`JPbx2!2maxaCrzSAWsQC;{!FKUO&8tR?=zERPR=jq|G(#+@B8lkq4U>v z!-N#b&(~iVj|19l@kU`uUtU}&TwQh_n!R}Sr*9ijtm7oZ+0_KQjzP@p`9g7VsZdc$ z^;Z@budV*4O5iSuXN%KkW&A_N9i6C!_yZ*V2q}4sFhdw8JVAJp@B(2g z;UeKR!WF`Mgl&Y6<%G|Xv?0>A4wE)Po=WnJk-eYV4p8MCO5G**5pp+)H+;bGy0{Oy zA4RLDxB6pbQ{dXJ&gT6GUFp?(oL-vc8GN2?g`gmH!GIO8L*U*Umz#s}fB!pv5N5I^o37(#6U5%vr*?J6Sn z55pw7O~yOml=5Xo&}(hkC0(Zw*>35|qTHilIELCu2#G20$+`wN_=d324gN8#bAvg7 zRc@#{h;cUrj$pm`%^R$Ie-@|FbVG1T{Oj#KdOKhMtYw95xFTBb*= z`D^sc%9j^^`}@LenKnqvc9C+s1*IJm{bpw}X@8K{tOveV$py>|vs^MW0%^blfIg7> zUYcxC`Hzd|W?QW-eG`DTF7^7deog69;!o3RZOv=rt@vP{WzBhtqtEi5V&AjOpxTnA zvipK^pA+3xcDUuHm~D|-OIf?Bv{|uIHKxxiJRx3I-PM;APK%L%HM(QD)|T5_BUb|; zsa{?z;qXS<=1(@%0ofjz-7;4^*|4<@*`_ep%uH#Xpw#wD_{-`*AKSa*du+swkzwQW`0xy`_|vseS@rtUTnh z8uE13jLp}HM?o8Jh!?>G-V__b9=)ivoCt&*Oo-7?L&b_JoXG}a^Kr2lYHn(j&kwxb z^vj$zg2Wtm0-?PNynC`-=D_6va#8btvUrmTGJ>V1D=Rof5a(+ORy6hPDp< zFdQilbVJ?aY_>W!UoX1C-;M1& 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