Fixed #1692 Properly distinguish obfuscated names vs namespace suffixes and attributes

This commit is contained in:
Jindra Petřík
2022-11-17 15:34:30 +01:00
parent 25cebd9e6b
commit 0227293bd0
21 changed files with 218 additions and 120 deletions

View File

@@ -48,9 +48,9 @@ public class AVM2Deobfuscation {
private final Map<String, Integer> usageTypesCount = new HashMap<>();
public static final DottedChain FLASH_PROXY = new DottedChain(new String[]{"flash", "utils", "flash_proxy"}, "");
public static final DottedChain FLASH_PROXY = new DottedChain(new String[]{"flash", "utils", "flash_proxy"});
public static final DottedChain BUILTIN = new DottedChain(new String[]{"-"}, "");
public static final DottedChain BUILTIN = new DottedChain(new String[]{"-"});
public AVM2Deobfuscation(SWF swf, AVM2ConstantPool constants) {
this.swf = swf;

View File

@@ -24,5 +24,5 @@ import com.jpexs.decompiler.graph.DottedChain;
*/
public interface AlchemyTypeIns {
public static final DottedChain ALCHEMY_PACKAGE = new DottedChain(new String[]{"avm2", "intrinsics", "memory"}, DottedChain.NO_SUFFIX);
public static final DottedChain ALCHEMY_PACKAGE = new DottedChain(new String[]{"avm2", "intrinsics", "memory"});
}

View File

@@ -44,17 +44,17 @@ import java.util.Objects;
*/
public class InitVectorAVM2Item extends AVM2Item {
public static final DottedChain VECTOR_PACKAGE = new DottedChain(new String[]{"__AS3__", "vec"}, "");
public static final DottedChain VECTOR_PACKAGE = new DottedChain(new String[]{"__AS3__", "vec"});
public static final DottedChain VECTOR_FQN = new DottedChain(new String[]{"__AS3__", "vec", "Vector"}, "");
public static final DottedChain VECTOR_FQN = new DottedChain(new String[]{"__AS3__", "vec", "Vector"});
public static final DottedChain VECTOR_INT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$int"}, "");
public static final DottedChain VECTOR_INT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$int"});
public static final DottedChain VECTOR_DOUBLE = new DottedChain(new String[]{"__AS3__", "vec", "Vector$double"}, "");
public static final DottedChain VECTOR_DOUBLE = new DottedChain(new String[]{"__AS3__", "vec", "Vector$double"});
public static final DottedChain VECTOR_UINT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$uint"}, "");
public static final DottedChain VECTOR_UINT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$uint"});
public static final DottedChain VECTOR_OBJECT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$object"}, "");
public static final DottedChain VECTOR_OBJECT = new DottedChain(new String[]{"__AS3__", "vec", "Vector$object"});
public GraphTargetItem subtype;

View File

@@ -746,7 +746,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
ret.add(ins(AVM2Instructions.NewObject, 0));
ret.add(ins(AVM2Instructions.PushWith));
scope = localData.scopeStack.size();
localData.scopeStack.add(new PropertyAVM2Item(null, item.functionName, abcIndex, new ArrayList<>(), localData.callStack));
localData.scopeStack.add(new PropertyAVM2Item(null, false, item.functionName, abcIndex, new ArrayList<>(), localData.callStack));
}
AVM2ConstantPool constants = abcIndex.getSelectedAbc().constants;
ret.add(ins(AVM2Instructions.NewFunction, method(false, constants.getStringId(item.functionName, true), true, false, localData.callStack, localData.pkg, item.needsActivation, item.subvariables, 0 /*Set later*/, item.hasRest, item.line, localData.currentClass, null, false, localData, item.paramTypes, item.paramNames, item.paramValues, item.body, item.retType)));
@@ -1349,7 +1349,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
*/
List<GraphTargetItem> getterBody = new ArrayList<>();
UnresolvedAVM2Item sp = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, false, TypeItem.UNBOUNDED, 0, new DottedChain(new String[]{"_skinParts"}, ""),
UnresolvedAVM2Item sp = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, false, TypeItem.UNBOUNDED, 0, new DottedChain(new String[]{"_skinParts"}),
null, openedNamespaces, abcIndex);
getterBody.add(new ReturnValueAVM2Item(null, null, sp));
List<AssignableAVM2Item> subvars = new ArrayList<>();
@@ -1850,7 +1850,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
continue;
}
NameAVM2Item d = new NameAVM2Item(n.type, n.line, n.getVariableName(), NameAVM2Item.getDefaultValue("" + n.type), true, n.openedNamespaces, abcIndex);
NameAVM2Item d = new NameAVM2Item(n.type, n.line, n.isAttribute(), n.getVariableName(), NameAVM2Item.getDefaultValue("" + n.type), true, n.openedNamespaces, abcIndex);
//no index
if (needsActivation) {
if (d.getSlotNumber() <= 0) {
@@ -1909,9 +1909,9 @@ public class AVM2SourceGenerator implements SourceGenerator {
mbody.traits.traits.add(tsc);
}
for (int i = 1; i < paramRegCount; i++) {
NameAVM2Item param = new NameAVM2Item(registerTypes.get(i), 0, registerNames.get(i), null, false, new ArrayList<>(), abcIndex);
NameAVM2Item param = new NameAVM2Item(registerTypes.get(i), 0, false, registerNames.get(i), null, false, new ArrayList<>(), abcIndex);
param.setRegNumber(i);
NameAVM2Item d = new NameAVM2Item(registerTypes.get(i), 0, registerNames.get(i), param, true, new ArrayList<>(), abcIndex);
NameAVM2Item d = new NameAVM2Item(registerTypes.get(i), 0, false, registerNames.get(i), param, true, new ArrayList<>(), abcIndex);
d.setSlotScope(slotScope);
d.setSlotNumber(slotNames.indexOf(registerNames.get(i)));
declarations.add(d);

View File

@@ -308,7 +308,7 @@ public class ActionScript3Parser {
s = lex();
GraphTargetItem ns = null;
if (s.type == SymbolType.NAMESPACE_OP) {
ns = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, false, null, lexer.yyline(), new DottedChain(new String[]{propName}, "" /*FIXME ???*/), null, openedNamespaces, abcIndex);
ns = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, false, null, lexer.yyline(), new DottedChain(new String[]{propName}, new String[]{""} /*FIXME ???*/), null, openedNamespaces, abcIndex);
variables.add((UnresolvedAVM2Item) ns);
s = lex();
if (s.type == SymbolType.BRACKET_OPEN) {
@@ -326,7 +326,7 @@ public class ActionScript3Parser {
if (ns != null) {
ret = new NamespacedAVM2Item(ns, propName, propItem, ret, attr, openedNamespaces, null);
} else {
ret = new PropertyAVM2Item(ret, (attr ? "@" : "") + propName, abcIndex, openedNamespaces, new ArrayList<>());
ret = new PropertyAVM2Item(ret, attr, propName, abcIndex, openedNamespaces, new ArrayList<>());
}
s = lex();
}
@@ -341,24 +341,31 @@ public class ActionScript3Parser {
private GraphTargetItem name(List<List<NamespaceItem>> allOpenedNamespaces, TypeItem thisType, NamespaceItem pkg, Reference<Boolean> needsActivation, boolean typeOnly, List<NamespaceItem> openedNamespaces, HashMap<String, Integer> registerVars, boolean inFunction, boolean inMethod, List<AssignableAVM2Item> variables, List<DottedChain> importedClasses) throws IOException, AVM2ParseException, InterruptedException {
ParsedSymbol s = lex();
DottedChain name = new DottedChain(new String[]{}, "");
DottedChain name = new DottedChain(new String[]{}, new String[]{""});
boolean attribute = false;
String name2 = "";
if (s.type == SymbolType.ATTRIBUTE) {
name2 += "@";
attribute = true;
s = lex();
}
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.THIS, SymbolType.SUPER, SymbolType.STRING_OP);
name2 += s.value.toString();
s = lex();
boolean attrBracket = false;
String nsSuffix = "";
if (s.type == SymbolType.NAMESPACESUFFIX) {
s = lex();
nsSuffix = "#" + s.value;
}
name = name.addWithSuffix(name2);
name = name.add(attribute, name2, nsSuffix);
while (s.isType(SymbolType.DOT)) {
//name += s.value.toString(); //. or ::
s = lex();
name2 = "";
attribute = false;
if (s.type == SymbolType.ATTRIBUTE) {
name2 += "@";
attribute = true;
s = lex();
if (s.type == SymbolType.MULTIPLY) {
name2 += s.value.toString();
@@ -370,19 +377,26 @@ public class ActionScript3Parser {
}
attrBracket = true;
continue;
}
}
} else {
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.NAMESPACE, SymbolType.MULTIPLY);
name2 += s.value.toString();
}
name = name.addWithSuffix(name2);
s = lex();
nsSuffix = "";
if (s.type == SymbolType.NAMESPACESUFFIX) {
nsSuffix = "#" + s.value;
s = lex();
}
name = name.add(attribute, name2, nsSuffix);
}
String nsname = null;
String nsprop = null;
boolean nsAtribute = false;
GraphTargetItem nspropItem = null;
if (s.type == SymbolType.NAMESPACE_OP) {
nsname = name.getLast();
nsAtribute = name.isLastAttribute();
s = lex();
if (s.group == SymbolGroup.IDENTIFIER) {
nsprop = s.value.toString();
@@ -401,14 +415,10 @@ public class ActionScript3Parser {
variables.add(unr);
ret = unr;
}
if (nsname != null) {
boolean attr = nsname.startsWith("@");
if (attr) {
nsname = nsname.substring(1);
}
UnresolvedAVM2Item ns = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, typeOnly, null, lexer.yyline(), new DottedChain(new String[]{nsname}, ""), null, openedNamespaces, abcIndex);
if (nsname != null) {
UnresolvedAVM2Item ns = new UnresolvedAVM2Item(new ArrayList<>(), importedClasses, typeOnly, null, lexer.yyline(), new DottedChain(new String[]{nsname}), null, openedNamespaces, abcIndex);
variables.add(ns);
ret = new NamespacedAVM2Item(ns, nsprop, nspropItem, ret, attr, openedNamespaces, null);
ret = new NamespacedAVM2Item(ns, nsprop, nspropItem, ret, nsAtribute, openedNamespaces, null);
}
if (s.type == SymbolType.BRACKET_OPEN) {
lexer.pushback(s);
@@ -543,14 +553,14 @@ public class ActionScript3Parser {
}
List<GraphTargetItem> body = null;
List<AssignableAVM2Item> subvariables = new ArrayList<>();
subvariables.add(new NameAVM2Item(thisType, lexer.yyline(), "this", null, true, openedNamespaces, abcIndex));
subvariables.add(new NameAVM2Item(thisType, lexer.yyline(), false, "this", null, true, openedNamespaces, abcIndex));
for (int i = 0; i < paramNames.size() - (hasRest ? 1 : 0); i++) {
subvariables.add(new NameAVM2Item(paramTypes.get(i), lexer.yyline(), paramNames.get(i), null, true, openedNamespaces, abcIndex));
subvariables.add(new NameAVM2Item(paramTypes.get(i), lexer.yyline(), false, paramNames.get(i), null, true, openedNamespaces, abcIndex));
}
if (hasRest) {
subvariables.add(new NameAVM2Item(TypeItem.UNBOUNDED, lexer.yyline(), paramNames.get(paramNames.size() - 1), null, true, openedNamespaces, abcIndex));
subvariables.add(new NameAVM2Item(TypeItem.UNBOUNDED, lexer.yyline(), false, paramNames.get(paramNames.size() - 1), null, true, openedNamespaces, abcIndex));
}
subvariables.add(new NameAVM2Item(thisType, lexer.yyline(), "arguments", null, true, openedNamespaces, abcIndex));
subvariables.add(new NameAVM2Item(thisType, lexer.yyline(), false, "arguments", null, true, openedNamespaces, abcIndex));
int parCnt = subvariables.size();
Reference<Boolean> needsActivation2 = new Reference<>(false);
if (!isInterface) {
@@ -1467,10 +1477,10 @@ public class ActionScript3Parser {
if (s.type == SymbolType.ASSIGN) {
GraphTargetItem varval = (expression(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables, false));
ret = new NameAVM2Item(type, lexer.yyline(), varIdentifier, varval, true, openedNamespaces, abcIndex);
ret = new NameAVM2Item(type, lexer.yyline(), false, varIdentifier, varval, true, openedNamespaces, abcIndex);
variables.add((NameAVM2Item) ret);
} else {
ret = new NameAVM2Item(type, lexer.yyline(), varIdentifier, null, true, openedNamespaces, abcIndex);
ret = new NameAVM2Item(type, lexer.yyline(), false, varIdentifier, null, true, openedNamespaces, abcIndex);
variables.add((NameAVM2Item) ret);
lexer.pushback(s);
}
@@ -1738,7 +1748,7 @@ public class ActionScript3Parser {
String enamestr = s.value.toString();
expectedType(SymbolType.COLON);
GraphTargetItem etype = type(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, variables);
NameAVM2Item e = new NameAVM2Item(etype, lexer.yyline(), enamestr, new ExceptionAVM2Item(null)/*?*/, true/*?*/, openedNamespaces, abcIndex);
NameAVM2Item e = new NameAVM2Item(etype, lexer.yyline(), false, enamestr, new ExceptionAVM2Item(null)/*?*/, true/*?*/, openedNamespaces, abcIndex);
variables.add(e);
catchExceptions.add(e);
e.setSlotNumber(1);
@@ -2491,8 +2501,8 @@ public class ActionScript3Parser {
}
s = lex();
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER);
DottedChain fullName = new DottedChain(new String[]{}, "");
fullName = fullName.addWithSuffix(s.value.toString());
DottedChain fullName = new DottedChain(new String[]{});
fullName = fullName.add(s.value.toString(), "");
s = lex();
boolean isStar = false;
while (s.type == SymbolType.DOT) {
@@ -2504,7 +2514,7 @@ public class ActionScript3Parser {
break;
}
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER);
fullName = fullName.addWithSuffix(s.value.toString());
fullName = fullName.add(s.value.toString(), "");
s = lex();
}

View File

@@ -1,26 +1,28 @@
/* The following code was generated by JFlex 1.6.0 */
/*
* Copyright (C) 2010-2022 JPEXS, All rights reserved.
*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.decompiler.flash.abc.avm2.parser.AVM2ParseException;
import java.io.StringReader;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;
import java.math.BigInteger;
/**

View File

@@ -98,11 +98,11 @@ public class CallAVM2Item extends AVM2Item {
}
}
if (cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, n.getVariableName(), outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueABC, isType)) {
NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), n.line, "this", null, false, n.openedNamespaces, abcIndex);
NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), n.line, false, "this", null, false, n.openedNamespaces, abcIndex);
nobj.setRegNumber(0);
obj = nobj;
}
PropertyAVM2Item p = new PropertyAVM2Item(obj, n.getVariableName(), g.abcIndex, n.openedNamespaces, new ArrayList<>());
PropertyAVM2Item p = new PropertyAVM2Item(obj, n.isAttribute(), n.getVariableName(), g.abcIndex, n.openedNamespaces, new ArrayList<>());
p.setAssignedValue(n.getAssignedValue());
callable = p;
}
@@ -143,7 +143,7 @@ public class CallAVM2Item extends AVM2Item {
}
if (cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, g.abcIndex, pkgName, cname, prop.propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType) && (localData.getFullClass().equals(outNs.getVal().addWithSuffix(outName.getVal()).toRawString()))) {
NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, "this", null, false, new ArrayList<>(), abcIndex);
NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, false, "this", null, false, new ArrayList<>(), abcIndex);
nobj.setRegNumber(0);
obj = nobj;
}

View File

@@ -49,6 +49,8 @@ import java.util.Objects;
*/
public class NameAVM2Item extends AssignableAVM2Item {
private boolean attribute;
private String variableName;
private boolean definition;
@@ -77,7 +79,7 @@ public class NameAVM2Item extends AssignableAVM2Item {
@Override
public AssignableAVM2Item copy() {
NameAVM2Item c = new NameAVM2Item(type, line, variableName, assignedValue, definition, openedNamespaces, abcIndex);
NameAVM2Item c = new NameAVM2Item(type, line, attribute, variableName, assignedValue, definition, openedNamespaces, abcIndex);
c.setNs(ns);
c.regNumber = regNumber;
c.unresolved = unresolved;
@@ -85,6 +87,12 @@ public class NameAVM2Item extends AssignableAVM2Item {
return c;
}
public boolean isAttribute() {
return attribute;
}
public void setSlotScope(int slotScope) {
this.slotScope = slotScope;
}
@@ -137,8 +145,9 @@ public class NameAVM2Item extends AssignableAVM2Item {
return variableName;
}
public NameAVM2Item(GraphTargetItem type, int line, String variableName, GraphTargetItem storeValue, boolean definition, List<NamespaceItem> openedNamespaces, AbcIndexing abcIndex) {
public NameAVM2Item(GraphTargetItem type, int line, boolean attribute, String variableName, GraphTargetItem storeValue, boolean definition, List<NamespaceItem> openedNamespaces, AbcIndexing abcIndex) {
super(storeValue);
this.attribute = attribute;
this.variableName = variableName;
this.assignedValue = storeValue;
this.definition = definition;

View File

@@ -86,7 +86,7 @@ public class NamespaceItem {
}
if (kind == Namespace.KIND_NAMESPACE) {
String custom = name.toRawString();
PropertyAVM2Item prop = new PropertyAVM2Item(null, custom, abcIndex, openedNamespaces, new ArrayList<>());
PropertyAVM2Item prop = new PropertyAVM2Item(null, false, custom, abcIndex, openedNamespaces, new ArrayList<>());
Reference<ValueKind> value = new Reference<>(null);
Reference<ABC> outAbc = new Reference<>(null);
Reference<Boolean> isType = new Reference<>(false);

View File

@@ -57,6 +57,8 @@ import java.util.logging.Logger;
*/
public class PropertyAVM2Item extends AssignableAVM2Item {
public boolean attribute;
public String propertyName;
public GraphTargetItem object;
@@ -71,11 +73,12 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
@Override
public AssignableAVM2Item copy() {
PropertyAVM2Item p = new PropertyAVM2Item(object, propertyName, abcIndex, openedNamespaces, callStack);
PropertyAVM2Item p = new PropertyAVM2Item(object, attribute, propertyName, abcIndex, openedNamespaces, callStack);
return p;
}
public PropertyAVM2Item(GraphTargetItem object, String propertyName, AbcIndexing abcIndex, List<NamespaceItem> openedNamespaces, List<MethodBody> callStack) {
public PropertyAVM2Item(GraphTargetItem object, boolean attribute, String propertyName, AbcIndexing abcIndex, List<NamespaceItem> openedNamespaces, List<MethodBody> callStack) {
this.attribute = attribute;
this.propertyName = propertyName;
this.object = object;
this.abcIndex = abcIndex;
@@ -160,7 +163,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
int propIndex = 0;
ABC abc = abcIndex.getSelectedAbc();
AVM2ConstantPool constants = abc.constants;
if (!propertyName.startsWith("@")) {
if (!attribute) {
if (scopeStack.isEmpty()) { //Everything is multiname when with command
if (objType == null) {
@@ -417,17 +420,16 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
if (propIndex == 0 && !mustExist) {
String pname = propertyName;
boolean attr = pname.startsWith("@");
if (attr) {
if (attribute) {
pname = pname.substring(1);
}
Multiname multiname;
if (attr && pname.isEmpty()) {
if (attribute && pname.isEmpty()) {
multiname = Multiname.createMultinameL(true,
constants.getNamespaceSetId(new int[]{constants.getNamespaceId(Namespace.KIND_PACKAGE_INTERNAL, localData.pkg, 0, true)}, true));
} else {
int name_index = constants.getStringId("*".equals(pname) ? null : pname, true); //Note: name = * is for .@* attribute
multiname = Multiname.createMultiname(attr, name_index, allNsSet(abcIndex));
multiname = Multiname.createMultiname(attribute, name_index, allNsSet(abcIndex));
}
propIndex = constants.getMultinameId(multiname, true);
propType = TypeItem.UNBOUNDED;
@@ -557,7 +559,7 @@ public class PropertyAVM2Item extends AssignableAVM2Item {
}
}
if (!localData.subMethod && cname != null && AVM2SourceGenerator.searchPrototypeChain(otherNs, localData.privateNs, localData.protectedNs, true, abcIndex, pkgName, cname, propertyName, outName, outNs, outPropNs, outPropNsKind, outPropNsIndex, outPropType, outPropValue, outPropValueAbc, isType) && (localData.getFullClass().equals(outNs.getVal().addWithSuffix(outName.getVal()).toRawString()))) {
NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, "this", null, false, openedNamespaces, abcIndex);
NameAVM2Item nobj = new NameAVM2Item(new TypeItem(localData.getFullClass()), 0, false, "this", null, false, openedNamespaces, abcIndex);
nobj.setRegNumber(0);
obj = nobj;
} else {

View File

@@ -295,13 +295,13 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
if (a instanceof NameAVM2Item) {
NameAVM2Item n = (NameAVM2Item) a;
if (n.isDefinition() && name.get(0).equals(n.getVariableName())) {
NameAVM2Item ret = new NameAVM2Item(n.type, n.line, name.get(0), null, false, openedNamespaces, abcIndex);
NameAVM2Item ret = new NameAVM2Item(n.type, n.line, name.isAttribute(0), name.get(0), null, false, openedNamespaces, abcIndex);
ret.setSlotScope(n.getSlotScope());
ret.setSlotNumber(n.getSlotNumber());
ret.setRegNumber(n.getRegNumber());
resolved = ret;
for (int i = 1; i < name.size(); i++) {
resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>());
resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>());
if (i == name.size() - 1) {
((PropertyAVM2Item) resolved).assignedValue = assignedValue;
}
@@ -325,10 +325,10 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
t = paramTypes.get(ind);
} //else rest parameter
GraphTargetItem ret = new NameAVM2Item(t, line, name.get(0), null, false, openedNamespaces, abcIndex);
GraphTargetItem ret = new NameAVM2Item(t, line, name.isAttribute(0), name.get(0), null, false, openedNamespaces, abcIndex);
resolved = ret;
for (int i = 1; i < name.size(); i++) {
resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>());
resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>());
if (i == name.size() - 1) {
((PropertyAVM2Item) resolved).assignedValue = assignedValue;
}
@@ -341,7 +341,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
boolean isProperty = false;
if (localData != null) { //resolve can be called without localData
PropertyAVM2Item resolvedx = new PropertyAVM2Item(null, name.get(0), abc, openedNamespaces, callStack);
PropertyAVM2Item resolvedx = new PropertyAVM2Item(null, name.isAttribute(0), name.get(0), abc, openedNamespaces, callStack);
((PropertyAVM2Item) resolvedx).scopeStack = scopeStack;
((PropertyAVM2Item) resolvedx).setAssignedValue(assignedValue);
Reference<GraphTargetItem> objectType = new Reference<>(null);
@@ -362,13 +362,13 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
DottedChain classChain = DottedChain.parseWithSuffix(currentClass);
DottedChain pkg = classChain.getWithoutLast();
TypeItem ti = new TypeItem(pkg.addWithSuffix(name.get(0)));
TypeItem ti = new TypeItem(pkg.addWithSuffix(name.get(0)));
AbcIndexing.ClassIndex ci = abc.findClass(ti);
if (ci != null) {
resolved = ti;
for (int i = 1; i < name.size(); i++) {
resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>());
resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>());
if (i == name.size() - 1) {
((PropertyAVM2Item) resolved).assignedValue = assignedValue;
}
@@ -387,7 +387,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
TypeItem ret = new TypeItem(imp);
resolved = ret;
for (int i = 1; i < name.size(); i++) {
resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>());
resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>());
if (i == name.size() - 1) {
((PropertyAVM2Item) resolved).assignedValue = assignedValue;
}
@@ -420,7 +420,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
TypeItem ret = new TypeItem(fname);
resolved = ret;
for (int j = i + 1; j < name.size(); j++) {
resolved = new PropertyAVM2Item(resolved, name.get(j), abc, openedNamespaces, new ArrayList<>());
resolved = new PropertyAVM2Item(resolved, name.isAttribute(j), name.get(j), abc, openedNamespaces, new ArrayList<>());
if (j == name.size() - 1) {
((PropertyAVM2Item) resolved).assignedValue = assignedValue;
}
@@ -449,7 +449,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
TypeItem ret = ti;
resolved = ret;
for (int i = 1; i < name.size(); i++) {
resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>());
resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>());
if (i == name.size() - 1) {
((PropertyAVM2Item) resolved).assignedValue = assignedValue;
}
@@ -483,10 +483,10 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
}
}
NameAVM2Item ret = new NameAVM2Item(ntype, line, name.get(0), null, false, openedNamespaces, abcIndex);
NameAVM2Item ret = new NameAVM2Item(ntype, line, name.isAttribute(0), name.get(0), null, false, openedNamespaces, abcIndex);
resolved = ret;
for (int i = 1; i < name.size(); i++) {
resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, new ArrayList<>());
resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, new ArrayList<>());
if (i == name.size() - 1) {
((PropertyAVM2Item) resolved).assignedValue = assignedValue;
}
@@ -509,7 +509,7 @@ public class UnresolvedAVM2Item extends AssignableAVM2Item {
resolved = null;
GraphTargetItem ret = null;
for (int i = 0; i < name.size(); i++) {
resolved = new PropertyAVM2Item(resolved, name.get(i), abc, openedNamespaces, callStack);
resolved = new PropertyAVM2Item(resolved, name.isAttribute(i), name.get(i), abc, openedNamespaces, callStack);
if (ret == null) {
((PropertyAVM2Item) resolved).scopeStack = scopeStack;
ret = resolved;

View File

@@ -418,7 +418,7 @@ public class Multiname {
if (ns != null) {
return ns.getName(constants).add(name, withSuffix ? getNamespaceSuffix() : "");
}
return new DottedChain(new String[]{name}, withSuffix ? getNamespaceSuffix() : "");
return new DottedChain(new String[]{name}, new String[]{withSuffix ? getNamespaceSuffix() : ""});
}
public Namespace getNamespace(AVM2ConstantPool constants) {

View File

@@ -1,16 +1,18 @@
/* The following code was generated by JFlex 1.6.0 */
/*
* Copyright (C) 2010-2022 JPEXS, All rights reserved.
*
* Copyright (C) 2010-2016 JPEXS, All rights reserved.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3.0 of the License, or (at your option) any later version.
*
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
*/

View File

@@ -167,7 +167,7 @@ public class LinkReportExporter {
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, uses, new DottedChain(new String[]{"FAKE!PACKAGE"}), new ArrayList<>());
for (Dependency dependency : dependencies) {
DottedChain dc = dependency.getId();
if (!"*".equals(dc.getLast())) {

View File

@@ -144,12 +144,12 @@ public class SwfToSwcExporter {
sb.append(" <def id=\"").append(defId).append("\" />\n");
Set<DottedChain> allDeps = new HashSet<>();
allDeps.add(new DottedChain(new String[]{"AS3"}, ""));
allDeps.add(new DottedChain(new String[]{"AS3"}, new String[]{""}));
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, uses, new DottedChain(new String[]{"NO:PACKAGE"}), new ArrayList<>());
for (Dependency d : dependencies) {
if ("*".equals(d.getId().getLast())) {

View File

@@ -30,41 +30,41 @@ import java.util.List;
*/
public class DottedChain implements Serializable, Comparable<DottedChain> {
public static final String NO_SUFFIX = "";
public static final DottedChain EMPTY = new DottedChain(true);
public static final DottedChain TOPLEVEL = new DottedChain(new String[]{}, NO_SUFFIX);
public static final DottedChain TOPLEVEL = new DottedChain(new String[]{});
public static final DottedChain BOOLEAN = new DottedChain(new String[]{"Boolean"}, NO_SUFFIX);
public static final DottedChain BOOLEAN = new DottedChain(new String[]{"Boolean"});
public static final DottedChain STRING = new DottedChain(new String[]{"String"}, NO_SUFFIX);
public static final DottedChain STRING = new DottedChain(new String[]{"String"});
public static final DottedChain ARRAY = new DottedChain(new String[]{"Array"}, NO_SUFFIX);
public static final DottedChain ARRAY = new DottedChain(new String[]{"Array"});
public static final DottedChain NUMBER = new DottedChain(new String[]{"Number"}, NO_SUFFIX);
public static final DottedChain NUMBER = new DottedChain(new String[]{"Number"});
public static final DottedChain OBJECT = new DottedChain(new String[]{"Object"}, NO_SUFFIX);
public static final DottedChain OBJECT = new DottedChain(new String[]{"Object"});
public static final DottedChain INT = new DottedChain(new String[]{"int"}, NO_SUFFIX);
public static final DottedChain INT = new DottedChain(new String[]{"int"});
public static final DottedChain UINT = new DottedChain(new String[]{"uint"}, NO_SUFFIX);
public static final DottedChain UINT = new DottedChain(new String[]{"uint"});
public static final DottedChain UNDEFINED = new DottedChain(new String[]{"Undefined"}, NO_SUFFIX);
public static final DottedChain UNDEFINED = new DottedChain(new String[]{"Undefined"});
public static final DottedChain XML = new DottedChain(new String[]{"XML"}, NO_SUFFIX);
public static final DottedChain XML = new DottedChain(new String[]{"XML"});
public static final DottedChain NULL = new DottedChain(new String[]{"null"}, NO_SUFFIX);
public static final DottedChain NULL = new DottedChain(new String[]{"null"});
public static final DottedChain FUNCTION = new DottedChain(new String[]{"Function"}, NO_SUFFIX);
public static final DottedChain FUNCTION = new DottedChain(new String[]{"Function"});
public static final DottedChain VOID = new DottedChain(new String[]{"void"}, NO_SUFFIX);
public static final DottedChain VOID = new DottedChain(new String[]{"void"});
public static final DottedChain NAMESPACE = new DottedChain(new String[]{"Namespace"}, NO_SUFFIX);
public static final DottedChain NAMESPACE = new DottedChain(new String[]{"Namespace"});
public static final DottedChain ALL = new DottedChain(new String[]{"*"}, NO_SUFFIX);
public static final DottedChain ALL = new DottedChain(new String[]{"*"});
private final String[] parts;
private final boolean[] attributes;
private final int length;
@@ -72,25 +72,42 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
private boolean isNull = false;
private String namespaceSuffix = "";
private String[] namespaceSuffixes;
public String getNamespaceSuffix() {
return namespaceSuffix;
public String getNamespaceSuffix(int index) {
return namespaceSuffixes[index];
}
public String getLastNamespaceSuffix() {
if (length == 0) {
return "";
}
return namespaceSuffixes[length - 1];
}
public static final DottedChain parseWithSuffix(String name) {
if (name == null) {
return DottedChain.EMPTY;
} else if (name.isEmpty()) {
return DottedChain.TOPLEVEL;
} else {
String nameNoSuffix = name;
String namespaceSuffix = "";
if (name.matches(".*#[0-9]+$")) {
nameNoSuffix = name.substring(0, name.lastIndexOf("#"));
namespaceSuffix = name.substring(name.lastIndexOf("#"));
String parts[] = name.split("\\.");
String nsSuffixes[] = new String[parts.length];
int i = 0;
for (String part : parts) {
String nameNoSuffix = part;
String namespaceSuffix = "";
if (part.matches(".*#[0-9]+$")) {
nameNoSuffix = part.substring(0, part.lastIndexOf("#"));
namespaceSuffix = part.substring(part.lastIndexOf("#"));
}
parts[i] = nameNoSuffix;
nsSuffixes[i] = namespaceSuffix;
i++;
}
return new DottedChain(nameNoSuffix.split("\\."), namespaceSuffix);
return new DottedChain(parts, nsSuffixes);
}
}
@@ -99,37 +116,58 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
this.parts = new String[0];
this.length = 0;
this.hash = 0;
this.attributes = new boolean[0];
this.namespaceSuffixes = new String[0];
}
public DottedChain(DottedChain src) {
this(src.parts, src.namespaceSuffix);
this(src.parts, src.namespaceSuffixes);
this.isNull = src.isNull;
}
public DottedChain(String[] parts) {
this(Arrays.asList(parts));
}
public DottedChain(List<String> parts) {
length = parts.size();
this.parts = parts.toArray(new String[length]);
attributes = new boolean[length];
hash = calcHash();
this.namespaceSuffixes = new String[length];
for(int i = 0; i < length; i++) {
namespaceSuffixes[i] = "";
}
}
/*public DottedChain(String onePart, String namespaceSuffix) {
this(new String[]{onePart}, namespaceSuffix);
}*/
public DottedChain(String[] parts, String namespaceSuffix) {
public DottedChain(String[] parts, String[] namespaceSuffixes) {
this(new boolean[parts.length], parts, namespaceSuffixes);
}
public DottedChain(boolean attributes[], String[] parts, String[] namespaceSuffixes) {
if (parts.length == 1 && parts[0].isEmpty()) {
length = 0;
this.parts = new String[0];
this.parts = new String[0];
} else {
length = parts.length;
this.parts = parts;
this.parts = parts;
}
this.attributes = attributes;
hash = calcHash();
this.namespaceSuffix = namespaceSuffix;
this.namespaceSuffixes = namespaceSuffixes;
}
private DottedChain(String[] parts, int length) {
this.length = length;
this.parts = parts;
attributes = new boolean[length];
this.namespaceSuffixes = new String[length];
for(int i = 0; i < length; i++) {
namespaceSuffixes[i] = "";
}
hash = calcHash();
}
@@ -152,6 +190,13 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
return parts[index];
}
public boolean isAttribute(int index) {
if (index >= length) {
throw new ArrayIndexOutOfBoundsException();
}
return attributes[index];
}
public DottedChain subChain(int count) {
if (count > length) {
@@ -171,6 +216,17 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
return parts[length - 1];
}
}
public boolean isLastAttribute() {
if (isNull) {
return false;
}
if (length == 0) {
return false;
} else {
return attributes[length - 1];
}
}
public DottedChain getWithoutLast() {
if (isNull) {
@@ -194,16 +250,25 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
}
public DottedChain add(String name, String namespaceSuffix) {
return add(false, name, namespaceSuffix);
}
public DottedChain add(boolean attribute, String name, String namespaceSuffix) {
if (name == null) {
return new DottedChain(this);
}
String[] nparts = new String[length + 1];
boolean[] nattributes = new boolean[length + 1];
String[] nnamespaceSuffixes = new String[length + 1];
if (length > 0) {
System.arraycopy(parts, 0, nparts, 0, length);
System.arraycopy(attributes, 0, nattributes, 0, length);
System.arraycopy(namespaceSuffixes, 0, nnamespaceSuffixes, 0, length);
}
nattributes[nattributes.length - 1] = attribute;
nparts[nparts.length - 1] = name;
return new DottedChain(nparts, namespaceSuffix);
nnamespaceSuffixes[nparts.length - 1] = namespaceSuffix;
return new DottedChain(nparts, nnamespaceSuffixes);
}
protected String toString(boolean as3, boolean raw, boolean withSuffix) {
@@ -223,10 +288,11 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
String part = parts[i];
boolean lastStar = i == length - 1 && "*".equals(part);
ret.append((raw || lastStar) ? part : IdentifiersDeobfuscation.printIdentifier(as3, part));
if (withSuffix) {
ret.append(namespaceSuffixes[i]);
}
}
if (withSuffix) {
ret.append(namespaceSuffix);
}
return ret.toString();
}
@@ -305,6 +371,12 @@ public class DottedChain implements Serializable, Comparable<DottedChain> {
if (!s1.equals(s2)) {
return false;
}
if (attributes[i] != other.attributes[i]) {
return false;
}
if (!namespaceSuffixes[i].equals(other.namespaceSuffixes[i])) {
return false;
}
}
return true;

View File

@@ -43,7 +43,7 @@ public class TypeItem extends GraphTargetItem {
public final DottedChain fullTypeName;
public TypeItem(String s) {
this(s == null ? new DottedChain(new String[]{}, "") : DottedChain.parseWithSuffix(s));
this(s == null ? new DottedChain(new String[]{}, new String[]{""}) : DottedChain.parseWithSuffix(s));
}
public TypeItem(DottedChain fullTypeName) {