From 4af3c0ca7e2195174326fa1fe02e10b370e4350c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 25 Sep 2023 07:31:41 +0200 Subject: [PATCH] Fixed #2086 AS3 direct editation - not deleting old nested methods when they have multiple usages --- CHANGELOG.md | 1 + .../com/jpexs/decompiler/flash/abc/ABC.java | 61 +++++++++++++++++-- .../flash/abc/types/MethodInfo.java | 6 +- 3 files changed, 62 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9b8b933a2..4bbddb788 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ All notable changes to this project will be documented in this file. - Proper error message when there is no room for new characters in the font (DefineFont1) - Synchronization problems when adding characters to the font vs its display - [#2086] AS3 direct editation - Correct class order (instanceinfo,classinfo) respecting extends/implements +- [#2086] AS3 direct editation - not deleting old nested methods when they have multiple usages ### Changed - [#2070] String values inside SWF to XML export are backslash escaped diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java index 7f6119ec0..af1c588a0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABC.java @@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code; import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool; import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscation; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; +import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.executing.CallPropertyIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushStringIns; import com.jpexs.decompiler.flash.abc.types.ABCException; @@ -80,6 +81,8 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -1613,7 +1616,7 @@ public class ABC implements Openable { } } } - + private int moveClassIndex(int oldIndex, int newIndex, int currentIndex) { if (newIndex > oldIndex) { newIndex--; @@ -1630,7 +1633,7 @@ public class ABC implements Openable { return currentIndex; } - public void moveClass(int oldIndex, int newIndex) { + public void moveClass(int oldIndex, int newIndex) { for (MethodBody b : bodies) { for (AVM2Instruction ins : b.getCode().code) { for (int i = 0; i < ins.definition.operands.length; i++) { @@ -1640,14 +1643,14 @@ public class ABC implements Openable { } } } - + for (ScriptInfo si : script_info) { moveClassInTraits(si.traits, oldIndex, newIndex); } for (MethodBody b : bodies) { moveClassInTraits(b.traits, oldIndex, newIndex); } - + if (newIndex > oldIndex) { newIndex--; } @@ -1837,6 +1840,56 @@ public class ABC implements Openable { } private void packMethods() { + Set newFunctionsToDelete = new LinkedHashSet<>(); + Map newFunctionsUsage = new HashMap<>(); + for (int m = 0; m < method_info.size(); m++) { + MethodBody body = findBody(m); + if (body != null) { + for (AVM2Instruction ins : body.getCode().code) { + if (ins.definition instanceof NewFunctionIns) { + if (ins.operands[0] < method_info.size()) { + if (method_info.get(m).deleted) { + if (!method_info.get(ins.operands[0]).deleted) { + newFunctionsToDelete.add(ins.operands[0]); + } + } else { + if (!newFunctionsUsage.containsKey(ins.operands[0])) { + newFunctionsUsage.put(ins.operands[0], 0); + } + newFunctionsUsage.put(ins.operands[0], newFunctionsUsage.get(ins.operands[0]) + 1); + } + } + } + } + } + } + + while(!newFunctionsToDelete.isEmpty()) { + Iterator it = newFunctionsToDelete.iterator(); + int m = it.next(); + it.remove(); + int usageCount = newFunctionsUsage.containsKey(m) ? newFunctionsUsage.get(m) : 0; + if (usageCount == 0 && !method_info.get(m).deleted) { + method_info.get(m).delete(this, true); + MethodBody body = findBody(m); + if (body != null) { + for (AVM2Instruction ins : body.getCode().code) { + if (ins.definition instanceof NewFunctionIns) { + if (ins.operands[0] < method_info.size()) { + if (!method_info.get(ins.operands[0]).deleted) { + newFunctionsToDelete.add(ins.operands[0]); + } + if (!newFunctionsUsage.containsKey(ins.operands[0])) { + newFunctionsUsage.put(ins.operands[0], 1); + } + newFunctionsUsage.put(ins.operands[0], newFunctionsUsage.get(ins.operands[0]) - 1); + } + } + } + } + } + } + for (int m = 0; m < method_info.size(); m++) { if (method_info.get(m).deleted) { removeMethod(m); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java index c957cca58..68852ab79 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodInfo.java @@ -43,7 +43,9 @@ public class MethodInfo { public void delete(ABC abc, boolean d) { this.deleted = d; - MethodBody body = abc.findBody(this); + + //NewFunctions are now deleted later, in ABC.pack + /*MethodBody body = abc.findBody(this); if (body != null) { for (AVM2Instruction ins : body.getCode().code) { if (ins.definition instanceof NewFunctionIns) { @@ -52,7 +54,7 @@ public class MethodInfo { } } } - } + }*/ } public int[] param_types = new int[]{};