diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java index 970fbce35..e23f8a083 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/FinalProcessLocalData.java @@ -33,6 +33,16 @@ public class FinalProcessLocalData { public final List loops; public Map> registerUsage; + public Set getRegisterUsage(int regIndex) { + if (registerUsage == null) { + return new HashSet<>(); + } + if (!registerUsage.containsKey(regIndex)) { + return new HashSet<>(); + } + return registerUsage.get(regIndex); + } + public FinalProcessLocalData(List loops) { temporaryRegisters = new HashSet<>(); registerUsage = new HashMap<>(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java index 879c317d7..266fe2ea4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/AVM2LocalData.java @@ -76,7 +76,7 @@ public class AVM2LocalData extends BaseLocalData { public boolean thisHasDefaultToPrimitive; - public Map> setLocalPosToGetLocalPos; + public Map> setLocalPosToGetLocalPos = new HashMap<>(); public AVM2LocalData() { 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 8df9a4524..6864565c2 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 @@ -284,7 +284,7 @@ public class AVM2Graph extends Graph { return; } if (ignoredSwitches.contains(q.end)) { - if (!next.equals(q.nextParts.get(0))) { //first is after finally + if (q.nextParts.isEmpty() || !next.equals(q.nextParts.get(0))) { //first is after finally return; } } @@ -616,6 +616,7 @@ public class AVM2Graph extends Graph { } output.clear(); stack.clear(); + makeAllCommands(tryCommands, st); output.add(new TryAVM2Item(tryCommands, catchedExceptions, catchedCommands, finallyCommands, finCatchName)); for (int fin_e : catchedFinallys) { if (finallyJumps.containsKey(fin_e)) { @@ -940,7 +941,7 @@ public class AVM2Graph extends Graph { if (next.start == fip) { if (stack != null && swip != -1) { AVM2Instruction swIns = avm2code.code.get(swip); - GraphTargetItem t = stack.pop(); + GraphTargetItem t = stack.peek(); Double dval = t.getResultAsNumber(); int val = (int) (double) dval; if (swIns.definition instanceof LookupSwitchIns) { @@ -1194,7 +1195,7 @@ public class AVM2Graph extends Graph { @Override protected void finalProcessAfter(List list, int level, FinalProcessLocalData localData, String path) { super.finalProcessAfter(list, level, localData, path); - for (int i = 0; i < list.size(); i++) { + /*for (int i = 0; i < list.size(); i++) { if (list.get(i) instanceof SetLocalAVM2Item) { SetLocalAVM2Item ri = (SetLocalAVM2Item) list.get(i); if (localData.temporaryRegisters.contains(ri.regIndex)) { @@ -1202,9 +1203,18 @@ public class AVM2Graph extends Graph { i--; } } - } + }*/ } + private boolean isIntegerOrPopInteger(GraphTargetItem item) { + if (item instanceof IntegerValueAVM2Item) { + return true; + } + if ((item instanceof PushItem) && (item.value instanceof IntegerValueAVM2Item)) { + return true; + } + return false; + } @Override protected void finalProcess(List list, int level, FinalProcessLocalData localData, String path) throws InterruptedException { @@ -1227,7 +1237,7 @@ public class AVM2Graph extends Graph { if (list.get(i) instanceof SetLocalAVM2Item) { SetLocalAVM2Item ri = (SetLocalAVM2Item) list.get(i); int setLocalIp = avm2code.adr2pos(ri.getSrc().getAddress()); - Set usages = localData.registerUsage.get(setLocalIp); + Set usages = localData.getRegisterUsage(setLocalIp); if (ri.value.getNotCoerced() instanceof ExceptionAVM2Item) { ExceptionAVM2Item ea = (ExceptionAVM2Item) ri.value.getNotCoerced(); if (ea.exception.isFinally()) { @@ -1261,7 +1271,7 @@ public class AVM2Graph extends Graph { } if (i + 2 < list.size()) { - if ((list.get(i + 1) instanceof IntegerValueAVM2Item) && (list.get(i + 2) instanceof ReturnValueAVM2Item) + if (isIntegerOrPopInteger(list.get(i + 1)) && (list.get(i + 2) instanceof ReturnValueAVM2Item) && (list.get(i + 2).value instanceof LocalRegAVM2Item) && (((LocalRegAVM2Item) list.get(i + 2).value).regIndex == ri.regIndex)) { ReturnValueAVM2Item r = (ReturnValueAVM2Item) list.get(i + 2); @@ -1271,7 +1281,7 @@ public class AVM2Graph extends Graph { i--; continue; } - if ((list.get(i + 1) instanceof IntegerValueAVM2Item) && (list.get(i + 2) instanceof ThrowAVM2Item) + if (isIntegerOrPopInteger(list.get(i + 1)) && (list.get(i + 2) instanceof ThrowAVM2Item) && (list.get(i + 2).value instanceof LocalRegAVM2Item) && (((LocalRegAVM2Item) list.get(i + 2).value).regIndex == ri.regIndex)) { ThrowAVM2Item t = (ThrowAVM2Item) list.get(i + 2); @@ -1282,8 +1292,11 @@ public class AVM2Graph extends Graph { continue; } } else if (i + 1 < list.size() && usages.isEmpty()) { - if (list.get(i + 1) instanceof IntegerValueAVM2Item) { + if (isIntegerOrPopInteger(list.get(i + 1))) { list.remove(i + 1); + list.remove(i); + i--; + continue; } } } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java index 180de3f0a..395cde4b4 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript3Test.java @@ -1264,6 +1264,83 @@ public class ActionScript3Test extends ActionScriptTestBase { false); } + @Test + public void testTryReturn2() { + decompileMethod("testTryReturn2", "var c:Boolean = false;\r\n" + + "trace(\"before\");\r\n" + + "var a:Boolean = true;\r\n" + + "var b:Boolean = false;\r\n" + + "c = true;\r\n" + + "var d:Boolean = false;\r\n" + + "var e:Boolean = true;\r\n" + + "try\r\n" + + "{\r\n" + + "if(a)\r\n" + + "{\r\n" + + "return \"A\";\r\n" + + "}\r\n" + + "if(b)\r\n" + + "{\r\n" + + "return \"B\";\r\n" + + "}\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "if(c)\r\n" + + "{\r\n" + + "return \"C\";\r\n" + + "}\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "if(d)\r\n" + + "{\r\n" + + "return \"D\";\r\n" + + "}\r\n" + + "if(e)\r\n" + + "{\r\n" + + "return \"E\";\r\n" + + "}\r\n" + + "}\r\n" + + "trace(\"after\");\r\n" + + "return \"X\";\r\n", + false); + } + + @Test + public void testUsagesTry() { + decompileMethod("testUsagesTry", "var k:int = 5;\r\n" + + "switch(k)\r\n" + + "{\r\n" + + "case 0:\r\n" + + "trace(\"1\");\r\n" + + "break;\r\n" + + "case 1:\r\n" + + "trace(\"2\");\r\n" + + "}\r\n" + + "var a:Boolean = true;\r\n" + + "var b:Boolean = true;\r\n" + + "try\r\n" + + "{\r\n" + + "if(b)\r\n" + + "{\r\n" + + "return \"B\";\r\n" + + "}\r\n" + + "trace(\"A\");\r\n" + + "}\r\n" + + "catch(e:Error)\r\n" + + "{\r\n" + + "trace(\"E\");\r\n" + + "}\r\n" + + "finally\r\n" + + "{\r\n" + + "trace(\"finally\");\r\n" + + "}\r\n" + + "trace(\"after\");\r\n" + + "return \"X\";\r\n", + false); + } + @Test public void testVector() { decompileMethod("testVector", "var v:Vector. = new Vector.();\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScriptTestBase.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScriptTestBase.java index f03fb56b1..b506b2f48 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScriptTestBase.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScriptTestBase.java @@ -12,7 +12,8 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library. */ + * License along with this library. + */ package com.jpexs.decompiler.flash; /** @@ -22,6 +23,7 @@ package com.jpexs.decompiler.flash; public class ActionScriptTestBase { protected String cleanPCode(String pCode) { + pCode = pCode.replaceAll("\t", " ").trim(); pCode = pCode.replaceAll("( *[\r\n]+ *)+", "\n").trim(); pCode = pCode.replaceAll(" +", " ").trim(); return pCode; diff --git a/libsrc/ffdec_lib/testdata/flashdevelop/bin/flashdevelop.swf b/libsrc/ffdec_lib/testdata/flashdevelop/bin/flashdevelop.swf index fb526fa78..983c5d22f 100644 Binary files a/libsrc/ffdec_lib/testdata/flashdevelop/bin/flashdevelop.swf and b/libsrc/ffdec_lib/testdata/flashdevelop/bin/flashdevelop.swf differ diff --git a/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.old b/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.old index c44f2164e..25aaf34a7 100644 --- a/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.old +++ b/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.old @@ -16,7 +16,7 @@ CONFIG::timeStamp - '24.01.2021' + '25.01.2021' CONFIG::air diff --git a/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.xml b/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.xml index c44f2164e..25aaf34a7 100644 --- a/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.xml +++ b/libsrc/ffdec_lib/testdata/flashdevelop/obj/flashdevelopConfig.xml @@ -16,7 +16,7 @@ CONFIG::timeStamp - '24.01.2021' + '25.01.2021' CONFIG::air diff --git a/libsrc/ffdec_lib/testdata/flashdevelop/src/Main.as b/libsrc/ffdec_lib/testdata/flashdevelop/src/Main.as index ba8a5c618..71a5f74bc 100644 --- a/libsrc/ffdec_lib/testdata/flashdevelop/src/Main.as +++ b/libsrc/ffdec_lib/testdata/flashdevelop/src/Main.as @@ -77,6 +77,7 @@ package TestTry; TestTryReturn; TestTryReturn2; + TestUsagesTry; TestVector; TestVector2; TestWhileAnd; diff --git a/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestTryReturn2.as b/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestTryReturn2.as index 708a22ba9..f2b437bd3 100644 --- a/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestTryReturn2.as +++ b/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestTryReturn2.as @@ -6,10 +6,12 @@ package tests public function run() : String { trace("before"); + var a:Boolean = true; var b:Boolean = false; var c:Boolean = true; var d:Boolean = false; + var e:Boolean = true; try { if (a) @@ -23,14 +25,17 @@ package tests } catch (e:Error) { - if (d){ - return "D"; + if (c){ + return "C"; } } finally - { - if (c) { - return "C"; + { + if (d) { + return "D"; + } + if (e) { + return "E"; } } trace("after"); diff --git a/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestUsagesTry.as b/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestUsagesTry.as new file mode 100644 index 000000000..98d8bc376 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/flashdevelop/src/tests/TestUsagesTry.as @@ -0,0 +1,37 @@ +package tests +{ + public class TestUsagesTry + { + + public function run() : String + { + var k:int = 5; + switch(k){ + case 0: trace("1"); break; + case 1: trace("2"); break; + } + + var a:Boolean = true; + var b:Boolean = true; + try + { + if (b) { + return "B"; + } + trace("A"); + } + catch (e:Error) + { + trace("E"); + } + finally + { + trace("finally"); + } + trace("after"); + return "X"; + } + + } + +} \ No newline at end of file