diff --git a/src/com/jpexs/decompiler/flash/action/Action.java b/src/com/jpexs/decompiler/flash/action/Action.java index c6004ad93..3f9cbffb7 100644 --- a/src/com/jpexs/decompiler/flash/action/Action.java +++ b/src/com/jpexs/decompiler/flash/action/Action.java @@ -313,6 +313,16 @@ public class Action implements GraphSourceItem { return surroundWithAction(new byte[0], version); } + /** + * Gets the length of action converted to bytes + * + * @param version SWF version + * @return Length + */ + public int getBytesLength(int version) { + return getBytes(version).length; + } + /** * Surrounds byte array with Action header * @@ -370,7 +380,7 @@ public class Action implements GraphSourceItem { long offset = baseAddress; for (Action a : list) { a.setAddress(offset); - offset += a.getBytes(version).length; + offset += a.getBytesLength(version); } } @@ -455,6 +465,7 @@ public class Action implements GraphSourceItem { if (containers.containsKey(offset)) { for (int i = 0; i < containers.get(offset).size(); i++) { writer.appendNoHilight("}").newLine(); + lastPush = false; GraphSourceItemContainer cnt = containers.get(offset).get(i); int cntPos = containersPos.get(cnt); writer.appendNoHilight(cnt.getASMSourceBetween(cntPos)); @@ -482,7 +493,7 @@ public class Action implements GraphSourceItem { if (pos + 1 < list.size()) { len = (int) (((Action) (list.get(pos + 1))).getAddress() - a.getAddress()); } else { - len = a.getBytes(version).length; + len = a.getBytesLength(version); } if (!(a instanceof ActionEnd)) { for (int i = 0; i < len; i++) { @@ -527,7 +538,7 @@ public class Action implements GraphSourceItem { writer.appendNoHilight("FFDec_DeobfuscatePop").newLine(); if (fixBranch == 0) { //jump writer.appendNoHilight("Jump loc"); - writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getBytes(version).length + ((ActionIf) a).getJumpOffset())); + writer.appendNoHilight(Helper.formatAddress(a.getAddress() + a.getBytesLength(version) + ((ActionIf) a).getJumpOffset())); } else { //nojump, ignore } @@ -636,7 +647,7 @@ public class Action implements GraphSourceItem { if (actions.isEmpty()) { return 0; } - return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getBytes(version).length; + return actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getBytesLength(version); } if (ip == -1) { return 0; @@ -659,7 +670,7 @@ public class Action implements GraphSourceItem { } } if (actions.size() > 0) { - long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getBytes(version).length; + long outpos = actions.get(actions.size() - 1).getAddress() + actions.get(actions.size() - 1).getBytesLength(version); if (addr == outpos) { return actions.size(); } diff --git a/src/com/jpexs/decompiler/flash/action/ActionListReader.java b/src/com/jpexs/decompiler/flash/action/ActionListReader.java index 45d178beb..81d43b48f 100644 --- a/src/com/jpexs/decompiler/flash/action/ActionListReader.java +++ b/src/com/jpexs/decompiler/flash/action/ActionListReader.java @@ -194,8 +194,8 @@ public class ActionListReader { updateJumps(actions, jumps, containerLastActions, endAddress); updateActionStores(actions, jumps); - updateContainerSizes(actions, containerLastActions); updateActionLengths(actions, version); + updateContainerSizes(actions, containerLastActions); if (SWFDecompilerPlugin.listener != null) { try { @@ -204,8 +204,8 @@ public class ActionListReader { updateAddresses(actions, 0, version); updateJumps(actions, jumps, containerLastActions, endAddress); updateActionStores(actions, jumps); - updateContainerSizes(actions, containerLastActions); updateActionLengths(actions, version); + updateContainerSizes(actions, containerLastActions); } catch (Throwable e) { View.showMessageDialog(null, "Failed to call plugin method actionListParsed. Exception: " + e.getMessage()); } @@ -407,7 +407,7 @@ public class ActionListReader { for (int i = 0; i < actions.size(); i++) { Action a = actions.get(i); a.setAddress(address); - int length = a.getBytes(version).length; + int length = a.getBytesLength(version); if ((i != actions.size() - 1) && (a instanceof ActionEnd)) { // placeholder for jump action length = new ActionDeobfuscateJump(0).getTotalActionLength(); @@ -420,7 +420,7 @@ public class ActionListReader { private static void updateActionLengths(List actions, int version) { for (int i = 0; i < actions.size(); i++) { Action a = actions.get(i); - int length = a.getBytes(version).length; + int length = a.getBytesLength(version); a.actionLength = length - 1 - ((a.actionCode >= 0x80) ? 2 : 0); } } @@ -599,8 +599,8 @@ public class ActionListReader { updateAddresses(actions, startIp, version); updateJumps(actions, jumps, containerLastActions, endAddress); updateActionStores(actions, jumps); - updateContainerSizes(actions, containerLastActions); updateActionLengths(actions, version); + updateContainerSizes(actions, containerLastActions); return true; } @@ -691,10 +691,10 @@ public class ActionListReader { for (long size : cnt.getContainerSizes()) { if (size != 0) { long ip2 = ip + actionLengthWithHeader; - //long endIp2 = ip + actionLengthWithHeader + size; + long endIp2 = ip + actionLengthWithHeader + size; readActionListAtPos(listeners, cpool, sis, actions, nextOffsets, - ip2, startIp, endIp, newPath, indeterminate, visitedContainers); + ip2, startIp, endIp2, newPath, indeterminate, visitedContainers); actionLengthWithHeader += size; } } diff --git a/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java b/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java index d3cece600..f8f983d85 100644 --- a/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java +++ b/src/com/jpexs/decompiler/flash/action/parser/pcode/ASMParser.java @@ -141,7 +141,7 @@ public class ASMParser { ActionConstantPool cpool = new ActionConstantPool(constantPool); cpool.setAddress(address); - address += cpool.getBytes(version).length; + address += cpool.getBytesLength(version); list.add(cpool); while (true) { @@ -185,7 +185,7 @@ public class ASMParser { address += 1; } else if (a != null) { a.setAddress(address); - address += a.getBytes(version).length; + address += a.getBytesLength(version); } if (a instanceof GraphSourceItemContainer) { containers.push((GraphSourceItemContainer) a); @@ -475,7 +475,7 @@ public class ASMParser { for (Label label : labels) { if (((ActionJump) link).identifier.equals(label.name)) { - ((ActionJump) link).setJumpOffset((int) (label.address - (((ActionJump) link).getAddress() + ((ActionJump) link).getBytes(version).length))); + ((ActionJump) link).setJumpOffset((int) (label.address - (((ActionJump) link).getAddress() + ((ActionJump) link).getBytesLength(version)))); found = true; break; } @@ -485,7 +485,7 @@ public class ASMParser { for (Label label : labels) { if (((ActionIf) link).identifier.equals(label.name)) { - ((ActionIf) link).setJumpOffset((int) (label.address - (((ActionIf) link).getAddress() + ((ActionIf) link).getBytes(version).length))); + ((ActionIf) link).setJumpOffset((int) (label.address - (((ActionIf) link).getAddress() + ((ActionIf) link).getBytesLength(version)))); found = true; break; } diff --git a/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java b/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java index 9062dba31..aaeb30197 100644 --- a/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java +++ b/src/com/jpexs/decompiler/flash/action/parser/script/ActionSourceGenerator.java @@ -157,7 +157,7 @@ public class ActionSourceGenerator implements SourceGenerator { || (((ActionJump) onTrue.get(onTrue.size() - 1)).isBreak)))) { ajmp = new ActionJump(0); ret.add(ajmp); - onTrueLen += ajmp.getBytes(SWF.DEFAULT_VERSION).length; + onTrueLen += ajmp.getBytesLength(SWF.DEFAULT_VERSION); } ifaif.setJumpOffset(onTrueLen); byte[] onFalseBytes = Action.actionsToBytes(onFalse, false, SWF.DEFAULT_VERSION); @@ -182,7 +182,7 @@ public class ActionSourceGenerator implements SourceGenerator { private void fixLoop(List code, int breakOffset, int continueOffset) { int pos = 0; for (Action a : code) { - pos += a.getBytes(SWF.DEFAULT_VERSION).length; + pos += a.getBytesLength(SWF.DEFAULT_VERSION); if (a instanceof ActionJump) { ActionJump aj = (ActionJump) a; if (aj.isContinue && (continueOffset != Integer.MAX_VALUE)) { @@ -248,8 +248,9 @@ public class ActionSourceGenerator implements SourceGenerator { ret.addAll(doExpr); ActionIf doif = new ActionIf(0); ret.add(doif); - doif.setJumpOffset(-doBodyLen - doExprLen - doif.getBytes(SWF.DEFAULT_VERSION).length); - fixLoop(doBody, doBodyLen + doExprLen + doif.getBytes(SWF.DEFAULT_VERSION).length, doBodyLen); + int offset = doBodyLen + doExprLen + doif.getBytesLength(SWF.DEFAULT_VERSION); + doif.setJumpOffset(-offset); + fixLoop(doBody, offset, doBodyLen); return ret; } @@ -264,7 +265,7 @@ public class ActionSourceGenerator implements SourceGenerator { ActionIf foraif = new ActionIf(0); forExpr.add(foraif); ActionJump forajmp = new ActionJump(0); - int forajmpLen = forajmp.getBytes(SWF.DEFAULT_VERSION).length; + int forajmpLen = forajmp.getBytesLength(SWF.DEFAULT_VERSION); int forExprLen = Action.actionsToBytes(forExpr, false, SWF.DEFAULT_VERSION).length; int forBodyLen = Action.actionsToBytes(forBody, false, SWF.DEFAULT_VERSION).length; int forFinalLen = Action.actionsToBytes(forFinalCommands, false, SWF.DEFAULT_VERSION).length; @@ -278,6 +279,7 @@ public class ActionSourceGenerator implements SourceGenerator { fixLoop(forBody, forBodyLen + forFinalLen + forajmpLen, forBodyLen); return ret; } + private long uniqLast = 0; public String uniqId() { @@ -371,7 +373,7 @@ public class ActionSourceGenerator implements SourceGenerator { jmpPos += exprLengths.get(k).get(m); } } - jmpPos += defJump.getBytes(SWF.DEFAULT_VERSION).length; + jmpPos += defJump.getBytesLength(SWF.DEFAULT_VERSION); for (int n = 0; n < i; n++) { jmpPos += caseLengths.get(n); } diff --git a/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java b/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java index e9f0c733b..343002859 100644 --- a/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java +++ b/src/com/jpexs/decompiler/flash/action/swf4/ActionIf.java @@ -76,7 +76,7 @@ public class ActionIf extends Action { @Override public String getASMSource(List container, List knownAddreses, List constantPool, int version, ScriptExportMode exportMode) { - String ofsStr = Helper.formatAddress(getAddress() + getBytes(version).length + offset); + String ofsStr = Helper.formatAddress(getAddress() + getBytesLength(version) + offset); return "If loc" + ofsStr + (!jumpUsed ? " ;compileTimeIgnore" : (!ignoreUsed ? " ;compileTimeJump" : "")); } @@ -98,10 +98,12 @@ public class ActionIf extends Action { @Override public List getBranches(GraphSource code) { List ret = super.getBranches(code); - int jmp = code.adr2pos(getAddress() + getBytes(((ActionGraphSource) code).version).length + offset); - int after = code.adr2pos(getAddress() + getBytes(((ActionGraphSource) code).version).length); + int version = ((ActionGraphSource) code).version; + int length = getBytesLength(version); + int jmp = code.adr2pos(getAddress() + length + offset); + int after = code.adr2pos(getAddress() + length); if (jmp == -1) { - Logger.getLogger(ActionIf.class.getName()).log(Level.SEVERE, "Invalid IF jump to ofs" + Helper.formatAddress(getAddress() + getBytes(((ActionGraphSource) code).version).length + offset)); + Logger.getLogger(ActionIf.class.getName()).log(Level.SEVERE, "Invalid IF jump to ofs" + Helper.formatAddress(getAddress() + length + offset)); ret.add(after); } else { ret.add(jmp); diff --git a/src/com/jpexs/decompiler/flash/action/swf4/ActionJump.java b/src/com/jpexs/decompiler/flash/action/swf4/ActionJump.java index 768a5ea7e..d423d24ec 100644 --- a/src/com/jpexs/decompiler/flash/action/swf4/ActionJump.java +++ b/src/com/jpexs/decompiler/flash/action/swf4/ActionJump.java @@ -76,12 +76,12 @@ public class ActionJump extends Action { @Override public String getASMSource(List container, List knownAddreses, List constantPool, int version, ScriptExportMode exportMode) { - String ofsStr = Helper.formatAddress(getAddress() + getBytes(version).length + offset); + String ofsStr = Helper.formatAddress(getAddress() + getBytesLength(version) + offset); return "Jump loc" + ofsStr; } public ActionJump(FlasmLexer lexer) throws IOException, ParseException { - super(0x99, 0); + super(0x99, 2); identifier = lexIdentifier(lexer); } @@ -98,11 +98,12 @@ public class ActionJump extends Action { @Override public List getBranches(GraphSource code) { List ret = super.getBranches(code); - int ofs = code.adr2pos(getAddress() + getBytes(((ActionGraphSource) code).version).length + offset); + int version = ((ActionGraphSource) code).version; + int length = getBytesLength(version); + int ofs = code.adr2pos(getAddress() + length + offset); if (ofs == -1) { - ofs = code.adr2pos(getAddress() + getBytes(((ActionGraphSource) code).version).length); - new Exception().printStackTrace(); - Logger.getLogger(ActionJump.class.getName()).log(Level.SEVERE, "Invalid jump to ofs" + Helper.formatAddress(getAddress() + getBytes(((ActionGraphSource) code).version).length + offset) + " from ofs" + Helper.formatAddress(getAddress())); + ofs = code.adr2pos(getAddress() + length); + Logger.getLogger(ActionJump.class.getName()).log(Level.SEVERE, "Invalid jump to ofs" + Helper.formatAddress(getAddress() + length + offset) + " from ofs" + Helper.formatAddress(getAddress())); } ret.add(ofs); return ret; diff --git a/test/com/jpexs/decompiler/flash/ActionScript2ModificationTest.java b/test/com/jpexs/decompiler/flash/ActionScript2ModificationTest.java index 245ca58af..ce7cd81a0 100644 --- a/test/com/jpexs/decompiler/flash/ActionScript2ModificationTest.java +++ b/test/com/jpexs/decompiler/flash/ActionScript2ModificationTest.java @@ -46,6 +46,7 @@ public class ActionScript2ModificationTest extends ActionStript2TestBase { public void init() throws IOException, InterruptedException { Main.initLogging(false); Configuration.autoDeobfuscate.set(false); + Configuration.pluginPath.set(null); swf = new SWF(new BufferedInputStream(new FileInputStream("testdata/as2/as2.swf")), false); } @@ -69,15 +70,21 @@ public class ActionScript2ModificationTest extends ActionStript2TestBase { public void testRemoveAction() { String actionsString = "ConstantPool\n" + - "Push 1\n" + - "Jump l1\n" + - "l1:Push 2"; + "DefineFunction \"test\" 1 \"p1\" {\n" + + "Push 1\n" + + "}\n" + + "Push 2\n" + + "Jump label1\n" + + "label1:Push 3"; String expectedResult = "ConstantPool\n" + - "Push 1 2\n"; + "DefineFunction \"test\" 1 \"p1\" {\n" + + "Push 1\n" + + "}\n" + + "Push 2 3"; try { ActionList actions = ASMParser.parse(0, true, actionsString, swf.version, false); - actions.removeAction(2); + actions.removeAction(4); // jump DoActionTag doa = getFirstActionTag(); doa.setActionBytes(Action.actionsToBytes(actions, true, swf.version));