Fixed AS1/2 DefineFunction cleaner

This commit is contained in:
Jindra Petřík
2021-11-21 10:22:11 +01:00
parent 21bedc7182
commit 9969a5cae5
4 changed files with 80 additions and 3 deletions

View File

@@ -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

View File

@@ -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;
}
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<Action> 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<Action> 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);
}

View File

@@ -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<Long>(), 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());

View File

@@ -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"
+ "};");
}
}