Fixed #1981 AS3 star import collisions

This commit is contained in:
Jindra Petřík
2023-03-01 19:30:19 +01:00
parent 60409accd0
commit f81d1ac58d
17 changed files with 171 additions and 163 deletions

View File

@@ -456,6 +456,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
abcIndex.addAbc(((ABCContainerTag) tag).getABC());
}
}
abcIndex.rebuildPkgToObjectsNameMap();
return abcIndex;
}

View File

@@ -40,6 +40,8 @@ import com.jpexs.helpers.Reference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
@@ -83,6 +85,7 @@ public final class AbcIndexing {
for (ABCContainerTag at : swf.getAbcList()) {
addAbc(at.getABC());
}
rebuildPkgToObjectsNameMap();
}
}
@@ -425,6 +428,8 @@ public final class AbcIndexing {
}
}
private Map<DottedChain, Set<String>> pkgToObjectsName = new LinkedHashMap<>();
private final Map<ClassDef, ClassIndex> classes = new HashMap<>();
private final Map<PropertyDef, TraitIndex> instanceProperties = new HashMap<>();
@@ -436,6 +441,36 @@ public final class AbcIndexing {
private final Map<PropertyNsDef, TraitIndex> classNsProperties = new HashMap<>();
private final Map<PropertyNsDef, TraitIndex> scriptProperties = new HashMap<>();
public void rebuildPkgToObjectsNameMap() {
pkgToObjectsName.clear();
for (ClassDef cd:classes.keySet()) {
if (!(cd.type instanceof TypeItem)) {
continue;
}
if (!pkgToObjectsName.containsKey(cd.pkg)) {
pkgToObjectsName.put(cd.pkg, new LinkedHashSet<>());
}
pkgToObjectsName.get(cd.pkg).add(((TypeItem)cd.type).fullTypeName.getLast());
}
for (PropertyNsDef nsdef:scriptProperties.keySet()) {
if (!pkgToObjectsName.containsKey(nsdef.ns)) {
pkgToObjectsName.put(nsdef.ns, new LinkedHashSet<>());
}
pkgToObjectsName.get(nsdef.ns).add(nsdef.propName);
}
}
public Set<String> getPackageObjects(DottedChain pkg) {
Set<String> classNames = new LinkedHashSet<>();
if (pkgToObjectsName.containsKey(pkg)) {
classNames.addAll(pkgToObjectsName.get(pkg));
}
if (parent != null) {
classNames.addAll(parent.getPackageObjects(pkg));
}
return classNames;
}
public ClassIndex findClass(GraphTargetItem cls, ABC abc, Integer scriptIndex) {
ClassDef keyWithScriptIndex = new ClassDef(cls, abc, scriptIndex);
@@ -717,6 +752,7 @@ public final class AbcIndexing {
}
removeAbc(abc);
addAbc(abc);
rebuildPkgToObjectsNameMap();
}
public void removeAbc(ABC abc) {
@@ -808,7 +844,7 @@ public final class AbcIndexing {
}
}
abcs.add(abc);
selectedAbc = abc;
selectedAbc = abc;
}
public void selectAbc(ABC abc) {
@@ -816,6 +852,7 @@ public final class AbcIndexing {
selectedAbc = abc;
} else {
addAbc(abc);
rebuildPkgToObjectsNameMap();
}
}

View File

@@ -49,6 +49,7 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
/**
*
@@ -170,14 +171,15 @@ public abstract class Trait implements Cloneable, Serializable {
return getName(abc).getNamespace(abc.constants).getName(abc.constants);
}
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
if (ignoredCustom == null) {
Namespace n = getName(abc).getNamespace(abc.constants);
if (n.kind == Namespace.KIND_NAMESPACE) {
ignoredCustom = n.getName(abc.constants).toRawString();
}
}
DependencyParser.parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE);
DependencyParser.parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE);
//DependencyParser.parseUsagesFromMultiname(ignoredCustom, abc, dependencies, getName(abc), ignorePackage, fullyQualifiedNames, DependencyType.NAMESPACE);
}
private static final String[] builtInClasses = {"ArgumentError", "arguments", "Array", "Boolean", "Class", "Date", "DefinitionError", "Error", "EvalError", "Function", "int", "JSON", "Math", "Namespace", "Number", "Object", "QName", "RangeError", "ReferenceError", "RegExp", "SecurityError", "String", "SyntaxError", "TypeError", "uint", "URIError", "VerifyError", "XML", "XMLList"};
@@ -190,23 +192,8 @@ public abstract class Trait implements Cloneable, Serializable {
}
return false;
}
public void writeUses(int scriptIndex, int classIndex, boolean isStatic, ABC abc, GraphTextWriter writer) throws InterruptedException {
List<Dependency> dependencies = new ArrayList<>();
List<String> uses = new ArrayList<>();
String customNs = null;
Namespace ns = getName(abc).getNamespace(abc.constants);
if (ns.kind == Namespace.KIND_NAMESPACE) {
customNs = ns.getName(abc.constants).toRawString();
}
getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, uses, null, new ArrayList<>());
for (String us : uses) {
writer.appendNoHilight("use namespace " + us + ";").newLine();
}
}
public void writeImportsUsages(int scriptIndex, int classIndex, boolean isStatic, ABC abc, GraphTextWriter writer, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void writeImports(AbcIndexing abcIndex, int scriptIndex, int classIndex, boolean isStatic, ABC abc, GraphTextWriter writer, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
List<String> namesInThisPackage = new ArrayList<>();
for (ABCContainerTag tag : abc.getAbcTags()) {
@@ -222,13 +209,12 @@ public abstract class Trait implements Cloneable, Serializable {
//imports
List<Dependency> dependencies = new ArrayList<>();
List<String> uses = new ArrayList<>();
String customNs = null;
Namespace ns = getName(abc).getNamespace(abc.constants);
if (ns.kind == Namespace.KIND_NAMESPACE) {
customNs = ns.getName(abc.constants).toRawString();
}
getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, uses, ignorePackage, new ArrayList<>());
getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, new ArrayList<>());
List<DottedChain> imports = new ArrayList<>();
for (Dependency d : dependencies) {
@@ -240,21 +226,21 @@ public abstract class Trait implements Cloneable, Serializable {
List<String> importnames = new ArrayList<>();
importnames.addAll(namesInThisPackage);
importnames.addAll(Arrays.asList(builtInClasses));
for (int i = 0; i < imports.size(); i++) {
DottedChain ipath = imports.get(i);
if (ipath.getWithoutLast().equals(ignorePackage)) { //do not check classes from same package, they are imported automatically
imports.remove(i);
i--;
continue;
}
String name = ipath.getLast();
if (importnames.contains(name)) {
fullyQualifiedNames.add(DottedChain.parseWithSuffix(name));
} else {
importnames.add(name);
for (DottedChain imp : imports) {
if (imp.getLast().equals("*")) {
Set<String> objectsInPkg = abcIndex.getPackageObjects(imp.getWithoutLast());
for (String objectName : objectsInPkg) {
if (importnames.contains(objectName)) {
fullyQualifiedNames.add(DottedChain.parseWithSuffix(objectName));
} else {
importnames.add(objectName);
}
}
}
}
for (int i = 0; i < imports.size(); i++) {
DottedChain imp = imports.get(i);
DottedChain pkg = imp.getWithoutLast();
@@ -268,6 +254,28 @@ public abstract class Trait implements Cloneable, Serializable {
i--;
}
}
for (int i = 0; i < imports.size(); i++) {
DottedChain ipath = imports.get(i);
String name = ipath.getLast();
if (ipath.getWithoutLast().equals(ignorePackage)) { //do not check classes from same package, they are imported automatically
if (importnames.contains(name)) {
fullyQualifiedNames.add(DottedChain.parseWithSuffix(name));
}
imports.remove(i);
i--;
continue;
}
if (importnames.contains(name)) {
fullyQualifiedNames.add(DottedChain.parseWithSuffix(name));
} else {
importnames.add(name);
}
}
boolean hasImport = false;
Collections.sort(imports);
@@ -291,12 +299,6 @@ public abstract class Trait implements Cloneable, Serializable {
if (hasImport) {
writer.newLine();
}
/*for (String us : uses) {
writer.appendNoHilight("use namespace " + us + ";").newLine();
}
if (uses.size() > 0) {
writer.newLine();
}*/
}
public final GraphTextWriter getMetaData(Trait parent, ConvertData convertData, ABC abc, GraphTextWriter writer) {

View File

@@ -78,31 +78,31 @@ public class TraitClass extends Trait implements TraitWithSlot {
}
@Override
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
super.getDependencies(scriptIndex, -1, false, customNs, abc, dependencies, uses, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames);
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
super.getDependencies(scriptIndex, -1, false, customNs, abc, dependencies, ignorePackage == null ? getPackage(abc) : ignorePackage, fullyQualifiedNames);
ClassInfo classInfo = abc.class_info.get(class_info);
InstanceInfo instanceInfo = abc.instance_info.get(class_info);
DottedChain packageName = instanceInfo.getName(abc.constants).getNamespace(abc.constants).getName(abc.constants); //assume not null name
//DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.name_index), packageName, fullyQualifiedNames);
if (instanceInfo.super_index > 0) {
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames, DependencyType.INHERITANCE);
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, abc.constants.getMultiname(instanceInfo.super_index), packageName, fullyQualifiedNames, DependencyType.INHERITANCE);
}
for (int i : instanceInfo.interfaces) {
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(i), packageName, fullyQualifiedNames, DependencyType.INHERITANCE);
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, abc.constants.getMultiname(i), packageName, fullyQualifiedNames, DependencyType.INHERITANCE);
}
//static
classInfo.static_traits.getDependencies(scriptIndex, class_info, true, customNs, abc, dependencies, uses, packageName, fullyQualifiedNames);
classInfo.static_traits.getDependencies(scriptIndex, class_info, true, customNs, abc, dependencies, packageName, fullyQualifiedNames);
//static initializer
DependencyParser.parseDependenciesFromMethodInfo(null, scriptIndex, class_info, true, customNs, abc, classInfo.cinit_index, dependencies, uses, packageName, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(null, scriptIndex, class_info, true, customNs, abc, classInfo.cinit_index, dependencies, packageName, fullyQualifiedNames, new ArrayList<>());
//instance
instanceInfo.instance_traits.getDependencies(scriptIndex, class_info, false, customNs, abc, dependencies, uses, packageName, fullyQualifiedNames);
instanceInfo.instance_traits.getDependencies(scriptIndex, class_info, false, customNs, abc, dependencies, packageName, fullyQualifiedNames);
//instance initializer
DependencyParser.parseDependenciesFromMethodInfo(null, scriptIndex, class_info, false, customNs, abc, instanceInfo.iinit_index, dependencies, uses, packageName, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(null, scriptIndex, class_info, false, customNs, abc, instanceInfo.iinit_index, dependencies, packageName, fullyQualifiedNames, new ArrayList<>());
}
@Override
@@ -123,7 +123,7 @@ public class TraitClass extends Trait implements TraitWithSlot {
DottedChain packageName = instanceInfoMultiname.getNamespace(abc.constants).getName(abc.constants); //assume not null name
fullyQualifiedNames = new ArrayList<>();
writeImportsUsages(scriptIndex, classIndex, false, abc, writer, packageName, fullyQualifiedNames);
writeImports(abcIndex, scriptIndex, classIndex, false, abc, writer, packageName, fullyQualifiedNames);
String instanceInfoName = instanceInfoMultiname.getName(abc.constants, fullyQualifiedNames, false, true);

View File

@@ -82,7 +82,7 @@ public class TraitFunction extends Trait implements TraitWithSlot {
@Override
public GraphTextWriter toString(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List<DottedChain> fullyQualifiedNames, boolean parallel) throws InterruptedException {
writeImportsUsages(scriptIndex, classIndex, false, abc, writer, getPackage(abc), fullyQualifiedNames);
writeImports(abcIndex, scriptIndex, classIndex, false, abc, writer, getPackage(abc), fullyQualifiedNames);
getMetaData(parent, convertData, abc, writer);
writer.startMethod(method_info);
toStringHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel);
@@ -105,7 +105,7 @@ public class TraitFunction extends Trait implements TraitWithSlot {
@Override
public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List<DottedChain> fullyQualifiedNames, boolean parallel) throws InterruptedException {
fullyQualifiedNames = new ArrayList<>();
writeImportsUsages(scriptIndex, classIndex, false, abc, writer, getPackage(abc), fullyQualifiedNames);
writeImports(abcIndex, scriptIndex, classIndex, false, abc, writer, getPackage(abc), fullyQualifiedNames);
writer.startMethod(method_info);
convertHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel);
int bodyIndex = abc.findBodyIndex(method_info);
@@ -133,14 +133,14 @@ public class TraitFunction extends Trait implements TraitWithSlot {
}
@Override
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
if (ignorePackage == null) {
ignorePackage = getPackage(abc);
}
super.getDependencies(scriptIndex, classIndex, false, customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
super.getDependencies(scriptIndex, classIndex, false, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames);
//if (method_info != 0)
{
DependencyParser.parseDependenciesFromMethodInfo(this, scriptIndex, classIndex, false, customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(this, scriptIndex, classIndex, false, customNs, abc, method_info, dependencies, ignorePackage, fullyQualifiedNames, new ArrayList<>());
}
}

View File

@@ -63,11 +63,11 @@ public class TraitMethodGetterSetter extends Trait {
}
@Override
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
if (ignorePackage == null) {
ignorePackage = getPackage(abc);
}
super.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
super.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames);
if (customNs == null) {
Namespace n = getName(abc).getNamespace(abc.constants);
@@ -77,7 +77,7 @@ public class TraitMethodGetterSetter extends Trait {
}
//if (method_info != 0)
{
DependencyParser.parseDependenciesFromMethodInfo(this, scriptIndex, classIndex, isStatic, customNs, abc, method_info, dependencies, uses, ignorePackage, fullyQualifiedNames, new ArrayList<>());
DependencyParser.parseDependenciesFromMethodInfo(this, scriptIndex, classIndex, isStatic, customNs, abc, method_info, dependencies, ignorePackage, fullyQualifiedNames, new ArrayList<>());
}
}
@@ -110,7 +110,7 @@ public class TraitMethodGetterSetter extends Trait {
@Override
public void convert(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, NulWriter writer, List<DottedChain> fullyQualifiedNames, boolean parallel) throws InterruptedException {
if (classIndex < 0) {
writeImportsUsages(scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames);
writeImports(abcIndex, scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames);
}
writer.startMethod(method_info);
path = path + "." + getName(abc).getName(abc.constants, fullyQualifiedNames, false, true);
@@ -132,7 +132,7 @@ public class TraitMethodGetterSetter extends Trait {
public GraphTextWriter toString(AbcIndexing abcIndex, Trait parent, ConvertData convertData, String path, ABC abc, boolean isStatic, ScriptExportMode exportMode, int scriptIndex, int classIndex, GraphTextWriter writer, List<DottedChain> fullyQualifiedNames, boolean parallel) throws InterruptedException {
if (classIndex < 0) {
writeImportsUsages(scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames);
writeImports(abcIndex, scriptIndex, classIndex, isStatic, abc, writer, getPackage(abc), fullyQualifiedNames);
}
getMetaData(parent, convertData, abc, writer);
writer.startMethod(method_info);

View File

@@ -221,12 +221,12 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
}
@Override
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
if (ignorePackage == null) {
ignorePackage = getPackage(abc);
}
super.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, uses, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames, DependencyType.SIGNATURE);
super.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames);
DependencyParser.parseDependenciesFromMultiname(customNs, abc, dependencies, abc.constants.getMultiname(type_index), getPackage(abc), fullyQualifiedNames, DependencyType.SIGNATURE);
}
@Override

View File

@@ -298,9 +298,9 @@ public class Traits implements Cloneable, Serializable {
}
}
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public void getDependencies(int scriptIndex, int classIndex, boolean isStatic, String customNs, ABC abc, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
for (Trait t : traits) {
t.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
t.getDependencies(scriptIndex, classIndex, isStatic, customNs, abc, dependencies, ignorePackage, fullyQualifiedNames);
}
}

View File

@@ -21,10 +21,15 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
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.alchemy.AlchemyTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructPropIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.FindPropertyStrictIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetSuperIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetPropertyIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetSuperIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.AsTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.types.CoerceIns;
import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item;
@@ -41,16 +46,36 @@ import java.util.List;
public class DependencyParser {
public static void parseDependenciesFromNS(String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, int namespace_index, DottedChain ignorePackage, String name, DependencyType dependencyType) {
public static void parseDependenciesFromNS(String ignoredCustom, ABC abc, List<Dependency> dependencies, int namespace_index, DottedChain ignorePackage, String name, DependencyType dependencyType) {
Namespace ns = abc.constants.getNamespace(namespace_index);
if (name.isEmpty()) {
name = "*";
}
DottedChain newimport = ns.getName(abc.constants);
if (parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, namespace_index, ignorePackage, name)) {
return;
} else if (ns.kind != Namespace.KIND_PACKAGE) { // && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) {
if (ns.kind == Namespace.KIND_NAMESPACE || ns.kind == Namespace.KIND_PACKAGE_INTERNAL) {
String nsVal = ns.getName(abc.constants).toRawString();
for (ABCContainerTag abcTag : abc.getAbcTags()) {
DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal);
if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) {
return; //builtin, no dependency
}
if (!nsimport.isEmpty()) {
Dependency depNs = new Dependency(nsimport, DependencyType.NAMESPACE);
if ((ignorePackage == null || !nsimport.getWithoutLast().equals(ignorePackage)) && !dependencies.contains(depNs)) {
dependencies.add(depNs);
}
if (ignoredCustom != null && nsVal.equals(ignoredCustom)) {
return;
}
return;
}
}
}
if (ns.kind != Namespace.KIND_PACKAGE) { // && (ns.kind != Namespace.KIND_PACKAGE_INTERNAL)) {
return;
}
newimport = newimport.addWithSuffix(name);
@@ -68,15 +93,15 @@ public class DependencyParser {
//}
}
public static void parseDependenciesFromMultiname(String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, DependencyType dependencyType) {
public static void parseDependenciesFromMultiname(String ignoredCustom, ABC abc, List<Dependency> dependencies, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, DependencyType dependencyType) {
if (m != null) {
if (m.kind == Multiname.TYPENAME) {
if (m.qname_index != 0) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType);
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType);
}
for (Integer i : m.params) {
if (i != 0) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType);
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType);
}
}
return;
@@ -85,35 +110,35 @@ public class DependencyParser {
String name = m.getName(abc.constants, fullyQualifiedNames, true, true);
NamespaceSet nss = m.getNamespaceSet(abc.constants);
if (ns != null) {
parseDependenciesFromNS(ignoredCustom, abc, dependencies, uses, m.namespace_index, ignorePackage, name, dependencyType);
parseDependenciesFromNS(ignoredCustom, abc, dependencies, m.namespace_index, ignorePackage, name, dependencyType);
}
if (nss != null) {
for (int n : nss.namespaces) {
parseDependenciesFromNS(ignoredCustom, abc, dependencies, uses, n, ignorePackage, nss.namespaces.length > 1 ? "" : name, dependencyType);
parseDependenciesFromNS(ignoredCustom, abc, dependencies, n, ignorePackage, nss.namespaces.length > 1 ? "" : name, dependencyType);
}
}
}
}
public static void parseDependenciesFromMethodInfo(Trait trait, int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, int method_index, List<Dependency> dependencies, List<String> uses, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, List<Integer> visitedMethods) throws InterruptedException {
public static void parseDependenciesFromMethodInfo(Trait trait, int scriptIndex, int classIndex, boolean isStatic, String ignoredCustom, ABC abc, int method_index, List<Dependency> dependencies, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, List<Integer> visitedMethods) throws InterruptedException {
if ((method_index < 0) || (method_index >= abc.method_info.size())) {
return;
}
visitedMethods.add(method_index);
if (abc.method_info.get(method_index).ret_type != 0) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE);
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(abc.method_info.get(method_index).ret_type), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE);
}
for (int t : abc.method_info.get(method_index).param_types) {
if (t != 0) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE);
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(t), ignorePackage, fullyQualifiedNames, DependencyType.SIGNATURE);
}
}
MethodBody body = abc.findBody(method_index);
if (body != null && body.convertException == null) {
body = body.convertMethodBodyCanUseLast(Configuration.autoDeobfuscate.get(), "", isStatic, scriptIndex, classIndex, abc, trait);
body.traits.getDependencies(scriptIndex, classIndex, isStatic, ignoredCustom, abc, dependencies, uses, ignorePackage, fullyQualifiedNames);
body.traits.getDependencies(scriptIndex, classIndex, isStatic, ignoredCustom, abc, dependencies, ignorePackage, fullyQualifiedNames);
for (ABCException ex : body.exceptions) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION /* or signature?*/);
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(ex.type_index), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION /* or signature?*/);
}
for (AVM2Instruction ins : body.getCode().code) {
if (ins.definition instanceof AlchemyTypeIns) {
@@ -126,93 +151,20 @@ public class DependencyParser {
if (ins.definition instanceof NewFunctionIns) {
if (ins.operands[0] != method_index) {
if (!visitedMethods.contains(ins.operands[0])) {
parseDependenciesFromMethodInfo(trait, scriptIndex, classIndex, isStatic, ignoredCustom, abc, ins.operands[0], dependencies, uses, ignorePackage, fullyQualifiedNames, visitedMethods);
parseDependenciesFromMethodInfo(trait, scriptIndex, classIndex, isStatic, ignoredCustom, abc, ins.operands[0], dependencies, ignorePackage, fullyQualifiedNames, visitedMethods);
}
}
}
if ((ins.definition instanceof FindPropertyStrictIns)
|| (ins.definition instanceof FindPropertyIns)
|| (ins.definition instanceof GetLexIns)
|| (ins.definition instanceof CoerceIns)
|| (ins.definition instanceof AsTypeIns)) {
int m = ins.operands[0];
if (m != 0) {
for (int k = 0; k < ins.definition.operands.length; k++) {
if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) {
int m = ins.operands[k];
if (m < abc.constants.getMultinameCount()) {
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION);
}
}
} else {
for (int k = 0; k < ins.definition.operands.length; k++) {
if (ins.definition.operands[k] == AVM2Code.DAT_MULTINAME_INDEX) {
int multinameIndex = ins.operands[k];
if (multinameIndex < abc.constants.getMultinameCount()) {
parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(multinameIndex), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION);
}
parseDependenciesFromMultiname(ignoredCustom, abc, dependencies, abc.constants.getMultiname(m), ignorePackage, fullyQualifiedNames, DependencyType.EXPRESSION);
}
}
}
}
}
}
public static void parseUsagesFromMultiname(String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, Multiname m, DottedChain ignorePackage, List<DottedChain> fullyQualifiedNames, DependencyType dependencyType) {
if (m != null) {
if (m.kind == Multiname.TYPENAME) {
if (m.qname_index != 0) {
parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(m.qname_index), ignorePackage, fullyQualifiedNames, dependencyType);
}
for (Integer i : m.params) {
if (i != 0) {
parseUsagesFromMultiname(ignoredCustom, abc, dependencies, uses, abc.constants.getMultiname(i), ignorePackage, fullyQualifiedNames, dependencyType);
}
}
return;
}
Namespace ns = m.getNamespace(abc.constants);
String name = m.getName(abc.constants, fullyQualifiedNames, false, true);
NamespaceSet nss = m.getNamespaceSet(abc.constants);
if (ns != null) {
parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, m.namespace_index, ignorePackage, name);
}
if (nss != null) {
if (nss.namespaces.length == 1) {
parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, nss.namespaces[0], ignorePackage, name);
} else {
for (int n : nss.namespaces) {
parseUsagesFromNS(ignoredCustom, abc, dependencies, uses, n, ignorePackage, "");
}
}
}
}
}
private static boolean parseUsagesFromNS(String ignoredCustom, ABC abc, List<Dependency> dependencies, List<String> uses, int namespace_index, DottedChain ignorePackage, String name) {
Namespace ns = abc.constants.getNamespace(namespace_index);
if (ns.kind == Namespace.KIND_NAMESPACE || ns.kind == Namespace.KIND_PACKAGE_INTERNAL) {
String nsVal = ns.getName(abc.constants).toRawString();
for (ABCContainerTag abcTag : abc.getAbcTags()) {
DottedChain nsimport = abcTag.getABC().nsValueToName(nsVal);
if (nsimport.equals(AVM2Deobfuscation.BUILTIN)) {
return true; //handled, but import/use not added
}
if (!nsimport.isEmpty()) {
Dependency depNs = new Dependency(nsimport, DependencyType.NAMESPACE);
if ((ignorePackage == null || !nsimport.getWithoutLast().equals(ignorePackage)) && !dependencies.contains(depNs)) {
dependencies.add(depNs);
}
if (ignoredCustom != null && nsVal.equals(ignoredCustom)) {
return true;
}
if (!uses.contains(nsimport.getLast())) {
uses.add(nsimport.getLast());
}
return true;
}
}
}
return false;
}
}
}

View File

@@ -163,11 +163,9 @@ public class LinkReportExporter {
reportTrait(scriptIndex, externalDefs, existingObjects, swf, abc, it);
}
List<Dependency> dependencies = new ArrayList<>();
List<String> uses = new ArrayList<>();
sb.append(indent(3)).append("<dep id=\"AS3\" />").append(newLineChar); //Automatic
tc.getDependencies(scriptIndex, -1, false, null, abc, dependencies, uses, new DottedChain(new String[]{"FAKE!PACKAGE"}), new ArrayList<>());
tc.getDependencies(scriptIndex, -1, false, null, abc, dependencies, new DottedChain(new String[]{"FAKE!PACKAGE"}), new ArrayList<>());
for (Dependency dependency : dependencies) {
DottedChain dc = dependency.getId();
if (!"*".equals(dc.getLast())) {

View File

@@ -148,8 +148,7 @@ public class SwfToSwcExporter {
sb.append(" <dep id=\"AS3\" type=\"").append(DEPENDENCY_NAMESPACE).append("\" />\n");
if (!skipDependencies) {
List<Dependency> dependencies = new ArrayList<>();
List<String> uses = new ArrayList<>();
pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(pack.scriptIndex, -1, false, null, pack.abc, dependencies, uses, new DottedChain(new String[]{"NO:PACKAGE"}), new ArrayList<>());
pack.abc.script_info.get(pack.scriptIndex).traits.getDependencies(pack.scriptIndex, -1, false, null, pack.abc, dependencies, new DottedChain(new String[]{"NO:PACKAGE"}), new ArrayList<>());
for (Dependency d : dependencies) {
if ("*".equals(d.getId().getLast())) {