diff --git a/CHANGELOG.md b/CHANGELOG.md index c02db382f..5660ce5eb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] ### Fixed - Japanese in english locales for Gotoaddress, addclass dialog +- AS1/2 DefineFunction cleaner ## [14.5.2] - 2021-11-20 ### Fixed diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionDefineFunctionPushRegistersCleaner.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionDefineFunctionPushRegistersCleaner.java index 72c2bdd46..8ecb32dde 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionDefineFunctionPushRegistersCleaner.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionDefineFunctionPushRegistersCleaner.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.action; import com.jpexs.decompiler.flash.SWF; @@ -206,7 +207,25 @@ public class ActionDefineFunctionPushRegistersCleaner extends SWFDecompilerAdapt return false; } - Iterator ait = code.getReferencesFor(asr); + Action actionWithRefs = asr; + + //Special: ignore zero jump when pushundefined is stripped as unreachable + if (code.get(pos - 1) instanceof ActionJump) { + if (((ActionJump) code.get(pos - 1)).getJumpOffset() == 0) { + Iterator zit = code.getReferencesFor(code.get(pos)); + int refCnt = 0; + while (zit.hasNext()) { + zit.next(); + refCnt++; + } + if (refCnt == 1) { + actionWithRefs = code.get(pos - 1); + pos--; + } + } + } + + Iterator ait = code.getReferencesFor(actionWithRefs); while (ait.hasNext()) { Action a = ait.next(); if (!(a instanceof ActionJump)) { @@ -215,6 +234,7 @@ public class ActionDefineFunctionPushRegistersCleaner extends SWFDecompilerAdapt jumpsToReturnPositions.add(code.indexOf(a)); } pos--; + if (!(code.get(pos) instanceof ActionJump)) { actionBeforeFinishPart = code.get(pos); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java index 6f7c134b4..c3757582a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/ActionListReader.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.action; import com.jpexs.decompiler.flash.DisassemblyListener; @@ -28,13 +29,16 @@ import com.jpexs.decompiler.flash.action.swf4.ActionJump; import com.jpexs.decompiler.flash.action.swf4.ActionPush; import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool; import com.jpexs.decompiler.flash.configuration.Configuration; +import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; import com.jpexs.decompiler.graph.GraphSourceItemContainer; import com.jpexs.helpers.CancellableWorker; +import com.jpexs.helpers.Helper; import com.jpexs.helpers.stat.Statistics; import java.io.IOException; import java.util.ArrayList; import java.util.HashMap; +import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; @@ -163,6 +167,13 @@ public class ActionListReader { } } + /*System.err.println("======================="); + int p = 0; + for (Action a : actions) { + System.err.println("loc" + Helper.formatAddress(a.getAddress()) + " (" + p + "): " + a.getASMSource(actions, new HashSet(), ScriptExportMode.PCODE)); + p++; + }*/ + //TODO: This cleaner needs to be executed only before actual decompilation, not when disassembly only try { new ActionDefineFunctionPushRegistersCleaner().actionListParsed(actions, sis.getSwf()); diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java index 30f6f7dff..d6cb83b02 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/ActionScript2AssemblerTest.java @@ -147,4 +147,49 @@ public class ActionScript2AssemblerTest extends ActionScript2TestBase { + "}\n" + "}"); } + + @Test + public void testDefineFuncRegCleaner() { + String res = decompilePcode("ConstantPool \"Math\" \"randi\" \"random\" \"b\" \"a\" \"floor\" \"randf\" \"randa\" \"arguments\" \"rande\" \"sign\" \"abs\"\n" + + "Push constant0\n" + + "GetVariable\n" + + "Push constant10\n" + + "definefunction \"\" 1 \"a\" { \n" + + "push register1 constant4\n" + + "getvariable\n" + + "storeregister 1\n" + + "pop\n" + + "push register1 0.0\n" + + "Equals2\n" + + "If locC\n" + + "push register1 1 constant0\n" + + "getvariable\n" + + "push constant11\n" + + "callmethod\n" + + "push register1\n" + + "divide\n" + + "jump locB\n" + + "locC:\n" + + "push 0.0\n" + + "locB: jump locA\n" + + "push undefined\n" + + "locA: storeregister 0\n" + + "pop\n" + + "storeregister 1\n" + + "pop\n" + + "push register0\n" + + "return\n" + + "}\n" + + "loc00a5:SetMember"); + res = cleanPCode(res); + assertEquals(res, "Math.sign = function(a)\n" + + "{\n" + + "var _loc1_ = a;\n" + + "if(_loc1_ != 0)\n" + + "{\n" + + "return Math.abs(_loc1_) / _loc1_;\n" + + "}\n" + + "return 0;\n" + + "};"); + } }