diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java index ffc64c1c5..e9fd525f7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/IdentifiersDeobfuscation.java @@ -48,7 +48,9 @@ public class IdentifiersDeobfuscation { public static final String VALID_NEXT_CHARACTERS = VALID_FIRST_CHARACTERS + "\\p{Nl}\\p{Mn}\\p{Mc}\\p{Nd}\\p{Pc}"; - public static final Pattern IDENTIFIER_PATTERN = Pattern.compile("^[" + VALID_FIRST_CHARACTERS + "][" + VALID_NEXT_CHARACTERS + "]*$"); + private static final Pattern VALID_NAME_PATTERN = Pattern.compile("^[a-zA-Z_\\$][a-zA-Z0-9_\\$]*$"); + + private static final Pattern IDENTIFIER_PATTERN = Pattern.compile("^[" + VALID_FIRST_CHARACTERS + "][" + VALID_NEXT_CHARACTERS + "]*$"); public static final String FOO_CHARACTERS = "bcdfghjklmnpqrstvwz"; @@ -88,8 +90,9 @@ public class IdentifiersDeobfuscation { return false; } String[] reservedWords = as3 ? reservedWordsAS3 : reservedWordsAS2; + s = s.trim(); for (String rw : reservedWords) { - if (rw.equals(s.trim())) { + if (rw.equals(s)) { return true; } } @@ -240,7 +243,7 @@ public class IdentifiersDeobfuscation { } // simple fast test - if (s.matches("^[a-zA-Z_\\$][a-zA-Z0-9_\\$]*$")) { + if (VALID_NAME_PATTERN.matcher(s).matches()) { return true; } // unicode test 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 cd917c937..4d857cfa1 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 @@ -527,7 +527,7 @@ public class ABC { class_info = new ArrayList<>(class_count); for (int i = 0; i < class_count; i++) { ais.newDumpLevel("class", "class_info"); - ClassInfo ci = new ClassInfo(); + ClassInfo ci = new ClassInfo(null); // do not create Traits in constructor ci.cinit_index = ais.readU30("cinit_index"); ci.static_traits = ais.readTraits("static_traits"); class_info.add(ci); @@ -537,7 +537,7 @@ public class ABC { script_info = new ArrayList<>(script_count); for (int i = 0; i < script_count; i++) { ais.newDumpLevel("script", "script_info"); - ScriptInfo si = new ScriptInfo(); + ScriptInfo si = new ScriptInfo(null); // do not create Traits in constructor si.init_index = ais.readU30("init_index"); si.traits = ais.readTraits("traits"); script_info.add(si); @@ -548,7 +548,7 @@ public class ABC { bodies = new ArrayList<>(bodies_count); for (int i = 0; i < bodies_count; i++) { ais.newDumpLevel("method_body", "method_body_info"); - MethodBody mb = new MethodBody(); + MethodBody mb = new MethodBody(null, null, null); // do not create Traits in constructor mb.method_info = ais.readU30("method_info"); mb.max_stack = ais.readU30("max_stack"); mb.max_regs = ais.readU30("max_regs"); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCInputStream.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCInputStream.java index 3f161eded..26b0ce09d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCInputStream.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/ABCInputStream.java @@ -50,6 +50,8 @@ public class ABCInputStream implements AutoCloseable { public static final boolean DEBUG_READ = false; public DumpInfo dumpInfo; + + private byte[] stringDataBuffer = new byte[256]; public void startBuffer() { if (bufferOs == null) { @@ -251,7 +253,8 @@ public class ABCInputStream implements AutoCloseable { } private long readLong() throws IOException { - byte[] readBuffer = safeRead(8); + safeRead(8, stringDataBuffer); + byte[] readBuffer = stringDataBuffer; return (((long) readBuffer[7] << 56) + ((long) (readBuffer[6] & 255) << 48) + ((long) (readBuffer[5] & 255) << 40) @@ -270,12 +273,10 @@ public class ABCInputStream implements AutoCloseable { return ret; } - private byte[] safeRead(int count) throws IOException { - byte[] ret = new byte[count]; + private void safeRead(int count, byte[] data) throws IOException { for (int i = 0; i < count; i++) { - ret[i] = (byte) readInternal(); + data[i] = (byte) readInternal(); } - return ret; } public Namespace readNamespace(String name) throws IOException { @@ -423,8 +424,7 @@ public class ABCInputStream implements AutoCloseable { public Traits readTraits(String name) throws IOException { newDumpLevel(name, "Traits"); int count = readU30("count"); - Traits traits = new Traits(); - traits.traits = new ArrayList<>(); + Traits traits = new Traits(count); for (int i = 0; i < count; i++) { traits.traits.add(readTrait("trait")); } @@ -456,7 +456,7 @@ public class ABCInputStream implements AutoCloseable { public InstanceInfo readInstanceInfo(String name) throws IOException { newDumpLevel(name, "instance_info"); - InstanceInfo ret = new InstanceInfo(); + InstanceInfo ret = new InstanceInfo(null); // do not create Traits in constructor ret.name_index = readU30("name_index"); ret.super_index = readU30("super_index"); ret.flags = readInternal(); @@ -477,8 +477,19 @@ public class ABCInputStream implements AutoCloseable { public String readString(String name) throws IOException { newDumpLevel(name, "String"); int length = readU30Internal(); - byte[] b = safeRead(length); - String r = new String(b, Utf8Helper.charset); + + // avoid creating new byte array every time + if (stringDataBuffer.length < length) { + int newLength = stringDataBuffer.length * 2; + while (newLength < length) { + newLength *= 2; + } + + stringDataBuffer = new byte[newLength]; + } + + safeRead(length, stringDataBuffer); + String r = new String(stringDataBuffer, 0, length, Utf8Helper.charset); endDumpLevel(r); return r; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java index ef463b91d..52ed58cc1 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/AVM2SourceGenerator.java @@ -1619,7 +1619,6 @@ public class AVM2SourceGenerator implements SourceGenerator { MethodBody mbody = new MethodBody(); if (needsActivation) { - mbody.traits = new Traits(); int slotId = 1; for (int i = 1; i < slotNames.size(); i++) { TraitSlotConst tsc = new TraitSlotConst(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ClassInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ClassInfo.java index e51332936..3e49550d6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ClassInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ClassInfo.java @@ -24,10 +24,18 @@ public class ClassInfo { public int cinit_index; //MethodInfo - static initializer - public Traits static_traits = new Traits(); + public Traits static_traits; public boolean deleted; + public ClassInfo() { + static_traits = new Traits(); + } + + public ClassInfo(Traits traits) { + static_traits = traits; + } + @Override public String toString() { return "method_index=" + cinit_index + "\r\n" + static_traits.toString(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java index 7f72c7bb6..d3d2352b9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/InstanceInfo.java @@ -39,7 +39,7 @@ public class InstanceInfo { public int iinit_index; // MethodInfo - constructor - public Traits instance_traits = new Traits(); + public Traits instance_traits; public static final int CLASS_SEALED = 1; //not dynamic @@ -51,6 +51,14 @@ public class InstanceInfo { public boolean deleted; + public InstanceInfo() { + instance_traits = new Traits(); + } + + public InstanceInfo(Traits traits) { + instance_traits = traits; + } + @Override public String toString() { return "name_index=" + name_index + " super_index=" + super_index + " flags=" + flags + " protectedNS=" + protectedNS + " interfaces=" + Helper.intArrToString(interfaces) + " method_index=" + iinit_index + "\r\n" + instance_traits.toString(); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MetadataInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MetadataInfo.java index 3de0e384c..5ff880362 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MetadataInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MetadataInfo.java @@ -39,17 +39,18 @@ public class MetadataInfo { } public String toString(AVM2ConstantPool constants) { - String s = "name=" + constants.getString(name_index); + StringBuilder sb = new StringBuilder(); + sb.append("name=").append(constants.getString(name_index)); if (keys.length > 0) { - s += "\r\n"; + sb.append("\r\n"); } for (int i = 0; i < keys.length; i++) { if (keys[i] == 0) { - s += "\"" + constants.getString(values[i]) + "\"\r\n"; + sb.append("\"").append(constants.getString(values[i])).append("\"\r\n"); } else { - s += "\"" + constants.getString(keys[i]) + "\"=\"" + constants.getString(values[i]) + "\"\r\n"; + sb.append("\"").append(constants.getString(keys[i])).append("\"=\"").append(constants.getString(values[i])).append("\"\r\n"); } } - return s; + return sb.toString(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java index b416ee26f..eecde5f17 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/MethodBody.java @@ -27,6 +27,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Traits; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; +import com.jpexs.decompiler.flash.types.annotations.Internal; import com.jpexs.decompiler.flash.types.annotations.SWFField; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphTargetItem; @@ -64,18 +65,32 @@ public final class MethodBody implements Cloneable { public int max_scope_depth; @SWFField - private byte[] codeBytes = new byte[0]; + private byte[] codeBytes; private AVM2Code code; - public ABCException[] exceptions = new ABCException[0]; + public ABCException[] exceptions; - public Traits traits = new Traits(); + public Traits traits; + @Internal public transient List convertedItems; + @Internal public transient Throwable convertException; + public MethodBody() { + this.traits = new Traits(); + this.codeBytes = new byte[0]; + this.exceptions = new ABCException[0]; + } + + public MethodBody(Traits traits, byte[] codeBytes, ABCException[] exceptions) { + this.traits = traits; + this.codeBytes = codeBytes; + this.exceptions = exceptions; + } + public synchronized void setCodeBytes(byte codeBytes[]) { this.codeBytes = codeBytes; this.code = null; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java index b7db0f3cc..e88f325d4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/Multiname.java @@ -280,10 +280,10 @@ public class Multiname { return ""; } if (name_index == 0) { - return (isAttribute() ? "@*" : "*"); + return isAttribute() ? "@*" : "*"; } else { String name = constants.getString(name_index); - if ((fullyQualifiedNames != null) && fullyQualifiedNames.contains(name)) { + if (fullyQualifiedNames != null && fullyQualifiedNames.contains(name)) { return getNameWithNamespace(constants, raw); } return (isAttribute() ? "@" : "") + (raw ? name : IdentifiersDeobfuscation.printIdentifier(true, name)); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java index 5fa0b4e70..7f37c8fdd 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/NamespaceSet.java @@ -32,13 +32,13 @@ public class NamespaceSet { } public String toString(AVM2ConstantPool constants) { - String s = ""; + StringBuilder sb = new StringBuilder(); for (int i = 0; i < this.namespaces.length; i++) { if (i > 0) { - s += ", "; + sb.append(", "); } - s += constants.getNamespace(namespaces[i]).getNameWithKind(constants); + sb.append(constants.getNamespace(namespaces[i]).getNameWithKind(constants)); } - return s; + return sb.toString(); } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java index 833c6bddc..8c68f705e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/ScriptInfo.java @@ -31,8 +31,16 @@ public class ScriptInfo { public int init_index; //MethodInfo - public Traits traits = new Traits(); + public Traits traits; + public ScriptInfo() { + traits = new Traits(); + } + + public ScriptInfo(Traits traits) { + this.traits = traits; + } + public List> getPacks(ABC abc, int scriptIndex) { List> ret = new ArrayList<>(); @@ -52,8 +60,8 @@ public class ScriptInfo { Namespace ns = name.getNamespace(abc.constants); if ((ns.kind == Namespace.KIND_PACKAGE_INTERNAL) || (ns.kind == Namespace.KIND_PACKAGE)) { - String packageName = ns.getName(abc.constants, false); //assume not null package - String objectName = name.getName(abc.constants, new ArrayList(), false); + String packageName = ns.getName(abc.constants, false); // assume not null package + String objectName = name.getName(abc.constants, null, false); List traitIndices = new ArrayList<>(); traitIndices.add(j); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java index 4c9781d0e..03a6658a0 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Trait.java @@ -30,13 +30,15 @@ import java.util.List; public abstract class Trait implements Serializable { + private static final int[] EMPTY_METADATA_ARRAY = new int[0]; + public int name_index; public int kindType; public int kindFlags; - public int[] metadata = new int[0]; + public int[] metadata = EMPTY_METADATA_ARRAY; public long fileOffset; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java index 259ad25d8..2919ab28a 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/types/traits/Traits.java @@ -34,8 +34,16 @@ import java.util.logging.Logger; public class Traits implements Serializable { - public List traits = new ArrayList<>(); + public List traits; + public Traits() { + traits = new ArrayList<>(); + } + + public Traits(int initialCapacity) { + traits = new ArrayList<>(initialCapacity); + } + public void delete(ABC abc, boolean d) { for (Trait t : traits) { t.delete(abc, d); diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties index a57d7d164..2a5d5710f 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_es.properties @@ -318,3 +318,5 @@ config.description.showTraitSavedMessage = Mostrar otra vez mensaje de rasgo gua config.name.updateProxyAddress = Http Proxy address for checking updates config.description.updateProxyAddress = Direcci\u00f3n del Proxy Http para comprobar actualizaciones. Formato: example.com:8080 +config.name.showDebugMenu = Mostrar men\u00fa de depuraci\u00f3n +config.description.showDebugMenu = Mostrar men\u00fa de depuraci\u00f3n en el ribbon diff --git a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ru.properties b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ru.properties index 1548052af..65d6b648c 100644 --- a/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ru.properties +++ b/src/com/jpexs/decompiler/flash/gui/locales/AdvancedSettingsDialog_ru.properties @@ -269,4 +269,7 @@ config.name.getLocalNamesFromDebugInfo = AS3: \u041f\u043e\u043b\u0443\u0447\u04 config.description.getLocalNamesFromDebugInfo = \u041f\u0435\u0440\u0435\u0438\u043c\u0435\u043d\u043e\u0432\u044b\u0432\u0430\u0435\u0442 \u043b\u043e\u043a\u0430\u043b\u044c\u043d\u044b\u0435 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u044b \u0438\u0437 _loc_x_ \u043d\u0430 \u0440\u0435\u0430\u043b\u044c\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430, \u0435\u0441\u043b\u0438 \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442 \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u0430\u044f \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f. \u041c\u043e\u0436\u043d\u043e \u043e\u0442\u043a\u043b\u044e\u0447\u0438\u0442\u044c, \u0442.\u043a. \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043e\u0431\u0444\u0443\u0441\u043a\u0430\u0442\u043e\u0440\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 \u0442\u0430\u043c \u043d\u0435\u0432\u0435\u0440\u043d\u044b\u0435 \u0438\u043c\u0435\u043d\u0430 \u0440\u0435\u0433\u0438\u0441\u0442\u0440\u043e\u0432. config.name.tagTreeShowEmptyFolders = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 -config.description.tagTreeShowEmptyFolders = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u0442\u044d\u0433\u043e\u0432. \ No newline at end of file +config.description.tagTreeShowEmptyFolders = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043f\u0443\u0441\u0442\u044b\u0435 \u043f\u0430\u043f\u043a\u0438 \u0432 \u0434\u0435\u0440\u0435\u0432\u0435 \u0442\u044d\u0433\u043e\u0432. + +config.name.showDebugMenu = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u043e\u0435 \u043c\u0435\u043d\u044e +config.description.showDebugMenu = \u041f\u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u043e\u0442\u043b\u0430\u0434\u043e\u0447\u043d\u043e\u0435 \u043c\u0435\u043d\u044e \u0432 \u0432\u0435\u0440\u0445\u043d\u0435\u0439 \u043f\u0430\u043d\u0435\u043b\u0438