various fixes for AS3 direct editation, decompilation, etc. to make FP ABC verifier happy

This commit is contained in:
Jindra Petřík
2015-11-08 11:15:18 +01:00
parent 90ee5282d7
commit 7057a0bdcb
20 changed files with 230 additions and 103 deletions

View File

@@ -74,7 +74,7 @@ public class SourceGeneratorLocalData implements Serializable {
public boolean isStatic = false;
public String getFullClass() {
return pkg.add(currentClass).toRawString();
return pkg == null ? currentClass : pkg.add(currentClass).toRawString();
}
public SourceGeneratorLocalData(HashMap<String, Integer> registerVars, Integer inFunction, Boolean inMethod, Integer forInLevel) {

View File

@@ -400,9 +400,9 @@ public class ABC {
// constant double
int constant_double_pool_count = ais.readU30("double_count");
constants.constant_double = new ArrayList<>(constant_double_pool_count);
if (constant_double_pool_count > 0) {
constants.addDouble(0);
}
//if (constant_double_pool_count > 0) {
constants.addDouble(0);
//}
if (constant_double_pool_count > 1) {
ais.newDumpLevel("doubles", "double[]");
for (int i = 1; i < constant_double_pool_count; i++) { // index 0 not used. Values 1..n-1
@@ -433,9 +433,9 @@ public class ABC {
int constant_string_pool_count = ais.readU30("string_count");
constants.constant_string = new ArrayList<>(constant_string_pool_count);
stringOffsets = new long[constant_string_pool_count];
if (constant_string_pool_count > 0) {
constants.addString("");
}
//if (constant_string_pool_count > 0) {
constants.addString(null);
//}
if (constant_string_pool_count > 1) {
ais.newDumpLevel("strings", "string[]");
for (int i = 1; i < constant_string_pool_count; i++) { // index 0 not used. Values 1..n-1
@@ -449,9 +449,9 @@ public class ABC {
// constant namespace
int constant_namespace_pool_count = ais.readU30("namespace_count");
constants.constant_namespace = new ArrayList<>(constant_namespace_pool_count);
if (constant_namespace_pool_count > 0) {
constants.addNamespace(null);
}
//if (constant_namespace_pool_count > 0) {
constants.addNamespace(null);
//}
if (constant_namespace_pool_count > 1) {
ais.newDumpLevel("namespaces", "namespace[]");
for (int i = 1; i < constant_namespace_pool_count; i++) { // index 0 not used. Values 1..n-1
@@ -463,9 +463,9 @@ public class ABC {
// constant namespace set
int constant_namespace_set_pool_count = ais.readU30("ns_set_count");
constants.constant_namespace_set = new ArrayList<>(constant_namespace_set_pool_count);
if (constant_namespace_set_pool_count > 0) {
constants.addNamespaceSet(null);
}
//if (constant_namespace_set_pool_count > 0) {
constants.addNamespaceSet(null);
//}
if (constant_namespace_set_pool_count > 1) {
ais.newDumpLevel("ns_sets", "ns_set[]");
for (int i = 1; i < constant_namespace_set_pool_count; i++) { // index 0 not used. Values 1..n-1
@@ -484,9 +484,9 @@ public class ABC {
// constant multiname
int constant_multiname_pool_count = ais.readU30("multiname_count");
constants.constant_multiname = new ArrayList<>(constant_multiname_pool_count);
if (constant_multiname_pool_count > 0) {
constants.addMultiname(null);
}
//if (constant_multiname_pool_count > 0) {
constants.addMultiname(null);
//}
if (constant_multiname_pool_count > 1) {
ais.newDumpLevel("multiname", "multinames[]");
for (int i = 1; i < constant_multiname_pool_count; i++) { // index 0 not used. Values 1..n-1

View File

@@ -1434,7 +1434,8 @@ public class AVM2Code implements Cloneable {
}
}
public List<GraphTargetItem> clearTemporaryRegisters(List<GraphTargetItem> output) {
public List<GraphTargetItem> clearTemporaryRegisters(List<GraphTargetItem> input) {
List<GraphTargetItem> output = new ArrayList<>(input);
for (int i = 0; i < output.size(); i++) {
if (output.get(i) instanceof SetLocalAVM2Item) {
if (isKilled(((SetLocalAVM2Item) output.get(i)).regIndex, 0, code.size() - 1)) {

View File

@@ -939,4 +939,10 @@ public class AVM2Graph extends Graph {
ret.scopeStack = copyScopeStack;
return ret;
}
@Override
protected List<GraphTargetItem> filter(List<GraphTargetItem> list) {
return avm2code.clearTemporaryRegisters(list);
}
}

View File

@@ -29,7 +29,7 @@ public class ConvertAVM2Item extends AVM2Item {
public GraphTargetItem type;
public ConvertAVM2Item(AVM2Instruction instruction, GraphTargetItem value, GraphTargetItem type) {
super(instruction, NOPRECEDENCE, value);
super(instruction, value.getPrecedence(), value);
this.type = type;
}

View File

@@ -78,11 +78,8 @@ public class NewFunctionAVM2Item extends AVM2Item {
abc.method_info.get(methodIndex).getReturnTypeStr(writer, abc.constants, fullyQualifiedNames);
writer.startBlock();
if (body != null) {
if (writer instanceof NulWriter) {
body.convert(new ConvertData(), path + "/inner", ScriptExportMode.AS, isStatic, methodIndex, scriptIndex, classIndex, abc, null, new ScopeStack(), 0, (NulWriter) writer, fullyQualifiedNames, null, false);
} else {
body.toString(path + "/inner", ScriptExportMode.AS, abc, null, writer, fullyQualifiedNames);
}
body.convert(new ConvertData(), path + "/inner", ScriptExportMode.AS, isStatic, methodIndex, scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), fullyQualifiedNames, null, false);
body.toString(path + "/inner", ScriptExportMode.AS, abc, null, writer, fullyQualifiedNames);
}
writer.endBlock();
writer.endMethod();

View File

@@ -46,6 +46,10 @@ public class SetSlotAVM2Item extends AVM2Item implements SetTypeAVM2Item, Assign
@Override
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
getSrcData().localName = slotName == null ? "/*UnknownSlot*/" : slotName.getName(localData.constantsAvm2, localData.fullyQualifiedNames, false);
if (getSrcData().localName.equals(value.toString(localData))) {
//assigning parameters to activation reg
return writer;
}
getName(writer, localData);
writer.append(" = ");
return value.toString(writer, localData);

View File

@@ -98,7 +98,6 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
@@ -1178,11 +1177,11 @@ public class AVM2SourceGenerator implements SourceGenerator {
instanceInfo.iinit_index = init = method(false, 0, false, isInterface, new ArrayList<>(), pkg, false, new ArrayList<>(), initScope + 1, false, 0, isInterface ? null : name, extendsVal != null ? extendsVal.toString() : null, true, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), TypeItem.UNBOUNDED/*?? FIXME*/);
} else {
MethodAVM2Item m = (MethodAVM2Item) constructor;
instanceInfo.iinit_index = init = method(false, 0, false, false, new ArrayList<>(), pkg, m.needsActivation, m.subvariables, initScope + 1, m.hasRest, m.line, name, extendsVal != null ? extendsVal.toString() : null, true, localData, m.paramTypes, m.paramNames, m.paramValues, m.body, TypeItem.UNBOUNDED/*?? FIXME*/);
instanceInfo.iinit_index = init = method(false, str(pkg.toRawString() + ":" + name + "/" + name), false, false, new ArrayList<>(), pkg, m.needsActivation, m.subvariables, initScope + 1, m.hasRest, m.line, name, extendsVal != null ? extendsVal.toString() : null, true, localData, m.paramTypes, m.paramNames, m.paramValues, m.body, TypeItem.UNBOUNDED/*?? FIXME*/);
}
//Class initializer
int staticMi = method(true, 0, false, false, new ArrayList<>(), pkg, staticNeedsActivation, sinitVariables, initScope + (implementsStr.isEmpty() ? 0 : 1), false, 0, isInterface ? null : name, superName, false, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), staticInit, TypeItem.UNBOUNDED);
int staticMi = method(true, str(""), false, false, new ArrayList<>(), pkg, staticNeedsActivation, sinitVariables, initScope + (implementsStr.isEmpty() ? 0 : 1), false, 0, isInterface ? null : name, superName, false, localData, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), staticInit, TypeItem.UNBOUNDED);
MethodBody sinitBody = abcIndex.getSelectedAbc().findBody(staticMi);
List<AVM2Instruction> sinitcode = new ArrayList<>();
@@ -1475,7 +1474,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
for (AssignableAVM2Item an : subvariables) {
if (an instanceof NameAVM2Item) {
NameAVM2Item n = (NameAVM2Item) an;
if (n.isDefinition()) {
if (n.isDefinition() && !registerNames.contains(n.getVariableName())) {
if (!needsActivation || (n.getSlotScope() <= 0)) {
String varName = n.getVariableName();
Matcher m = pat.matcher(varName);
@@ -1500,6 +1499,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
registerTypes.add(n.type.toString());
slotNames.add(n.getVariableName());
slotTypes.add(n.type.toString());
}
}
}
@@ -1908,7 +1908,8 @@ public class AVM2SourceGenerator implements SourceGenerator {
new Multiname(
Multiname.QNAME,
abcIndex.getSelectedAbc().constants.getStringId(((ClassAVM2Item) item).className, true),
abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abcIndex.getSelectedAbc().constants.getStringId(((ClassAVM2Item) item).pkg, true)), 0, true), 0, 0, new ArrayList<>()), true);
//abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abcIndex.getSelectedAbc().constants.getStringId(((ClassAVM2Item) item).pkg, true)), 0, true)
((ClassAVM2Item) item).namespace, 0, 0, new ArrayList<>()), true);
if (((ClassAVM2Item) item).extendsOp != null) {
instanceInfo.super_index = typeName(localData, ((ClassAVM2Item) item).extendsOp);
@@ -1987,7 +1988,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
if (mai.isStatic() != generateStatic) {
continue;
}
((TraitMethodGetterSetter) traits[k]).method_info = method(mai.isStatic(), abcIndex.getSelectedAbc().constants.getStringId(mai.functionName, true), false, isInterface, new ArrayList<>(), mai.pkg, mai.needsActivation, mai.subvariables, methodInitScope + (mai.isStatic() ? 0 : 1), mai.hasRest, mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType);
((TraitMethodGetterSetter) traits[k]).method_info = method(mai.isStatic(), abcIndex.getSelectedAbc().constants.getStringId(localData.pkg.toRawString() + ":" + localData.currentClass + "/" + (mai.isPrivate() ? "private:" : "") + mai.functionName, true), false, isInterface, new ArrayList<>(), mai.pkg, mai.needsActivation, mai.subvariables, methodInitScope + (mai.isStatic() ? 0 : 1), mai.hasRest, mai.line, className, superName, false, localData, mai.paramTypes, mai.paramNames, mai.paramValues, mai.body, mai.retType);
} else if (item instanceof FunctionAVM2Item) {
FunctionAVM2Item fai = (FunctionAVM2Item) item;
((TraitFunction) traits[k]).method_info = method(false, abcIndex.getSelectedAbc().constants.getStringId(fai.functionName, true), false, isInterface, new ArrayList<>(), fai.pkg, fai.needsActivation, fai.subvariables, methodInitScope, fai.hasRest, fai.line, className, superName, false, localData, fai.paramTypes, fai.paramNames, fai.paramValues, fai.body, fai.retType);
@@ -2144,7 +2145,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
abcIndex.refreshSelected();
MethodInfo mi = new MethodInfo(new int[0], 0, 0, 0, new ValueKind[0], new int[0]);
MethodInfo mi = new MethodInfo(new int[0], 0, abcIndex.getSelectedAbc().constants.getStringId("", true), 0, new ValueKind[0], new int[0]);
MethodBody mb = new MethodBody(abcIndex.getSelectedAbc(), new Traits(), new byte[0], new ABCException[0]);
mb.method_info = abcIndex.getSelectedAbc().addMethodInfo(mi);
mb.setCode(new AVM2Code());
@@ -2209,7 +2210,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
mb.autoFillStats(abcIndex.getSelectedAbc(), 1, false);
abcIndex.getSelectedAbc().addMethodBody(mb);
si.init_index = mb.method_info;
localData.pkg = null; //FIXME: pkg.packageName;
localData.pkg = DottedChain.EMPTY; //FIXME: pkg.packageName;
generateTraitsPhase3(1/*??*/, false, null, null, true, localData, commands, si.traits, traitArr, initScopes, class_index);
return si;
}
@@ -2291,7 +2292,8 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
outPropNs.setVal(sp.trait.getName(sp.abc).getNamespace(sp.abc.constants).getName(sp.abc.constants));
outPropNsKind.setVal(sp.trait.getName(sp.abc).getNamespace(sp.abc.constants).kind);
outPropNsIndex.setVal(selectedNs == 0 ? 0 : sp.abc.constants.getNamespaceSubIndex(selectedNs));
int nsi = sp.trait.getName(sp.abc).namespace_index;
outPropNsIndex.setVal(sp.abc == abc.getSelectedAbc() ? sp.abc.constants.getNamespaceSubIndex(nsi) : 0);
outPropType.setVal(sp.returnType);
outPropValue.setVal(sp.value);
outPropValueAbc.setVal(sp.abc);
@@ -2306,8 +2308,8 @@ public class AVM2SourceGenerator implements SourceGenerator {
int ni = ci.abc.instance_info.get(ci.index).name_index;
indices.add(ni);
outABCs.add(ci.abc);
names.add(abc.getSelectedAbc().constants.constant_multiname.get(ni).getName(abc.getSelectedAbc().constants, null, true));
namespaces.add(abc.getSelectedAbc().constants.constant_multiname.get(ni).getNamespace(abc.getSelectedAbc().constants).getName(abc.getSelectedAbc().constants).toRawString());
names.add(ci.abc.constants.constant_multiname.get(ni).getName(ci.abc.constants, null, true));
namespaces.add(ci.abc.constants.constant_multiname.get(ni).getNamespace(ci.abc.constants).getName(ci.abc.constants).toRawString());
ci = ci.parent;
}
}
@@ -2384,15 +2386,30 @@ public class AVM2SourceGenerator implements SourceGenerator {
DottedChain dname = type.fullTypeName;
String pkg = dname.getWithoutLast().toRawString();
String name = dname.getLast();
for (InstanceInfo ii : abc.getSelectedAbc().instance_info) {
Multiname mname = abc.getSelectedAbc().constants.constant_multiname.get(ii.name_index);
if (mname != null && name.equals(mname.getName(abc.getSelectedAbc().constants, null, true))) {
if (mname.getNamespace(abc.getSelectedAbc().constants).hasName(pkg, abc.getSelectedAbc().constants)) {
name_index = ii.name_index;
break;
}
/*for (InstanceInfo ii : abc.getSelectedAbc().instance_info) {
Multiname mname = abc.getSelectedAbc().constants.constant_multiname.get(ii.name_index);
if (mname != null && name.equals(mname.getName(abc.getSelectedAbc().constants, null, true))) {
Namespace ns = mname.getNamespace(abc.getSelectedAbc().constants);
if (ns != null && ns.hasName(pkg, abc.getSelectedAbc().constants)) {
name_index = ii.name_index;
break;
}
}
}*/
AbcIndexing.ClassIndex ci = abc.findClass(new TypeItem(dname));
if (ci != null) {
Multiname m = ci.abc.instance_info.get(ci.index).getName(ci.abc.constants);
if (m != null) {
Namespace ns = ci.abc.instance_info.get(ci.index).getName(ci.abc.constants).getNamespace(ci.abc.constants);
String n = m.getName(ci.abc.constants, new ArrayList<DottedChain>(), true);
String nsn = ns == null ? null : ns.getName(ci.abc.constants).toRawString();
name_index = abc.getSelectedAbc().constants.getQnameId(
n,
ns == null ? Namespace.KIND_PACKAGE : ns.kind,
nsn, true);
}
}
for (int i = 1; i < abc.getSelectedAbc().constants.constant_multiname.size(); i++) {
Multiname mname = abc.getSelectedAbc().constants.constant_multiname.get(i);
if (mname != null && name.equals(mname.getName(abc.getSelectedAbc().constants, null, true))) {

View File

@@ -195,6 +195,11 @@ public class AbcIndexing {
return propName;
}
@Override
public String toString() {
return ns.toString() + ":" + propName + (propNsIndex > 0 ? "[ns:" + propNsIndex + "]" : "");
}
public PropertyNsDef(String propName, DottedChain ns, ABC abc, int nsIndex) {
this.propName = propName;
this.ns = ns;
@@ -302,7 +307,14 @@ public class AbcIndexing {
}
public TraitIndex findScriptProperty(String propName, DottedChain ns) {
return scriptProperties.get(new PropertyNsDef(propName, ns, null, 0));
PropertyNsDef nsd = new PropertyNsDef(propName, ns, null, 0);
if (!scriptProperties.containsKey(nsd)) {
if (parent != null) {
return parent.findScriptProperty(propName, ns);
}
return null;
}
return scriptProperties.get(nsd);
}
public TraitIndex findNsProperty(PropertyNsDef prop, boolean findStatic, boolean findInstance) {
@@ -366,7 +378,7 @@ public class AbcIndexing {
//now search parent class
AbcIndexing.ClassIndex ci = findClass(prop.parent);
if (ci != null && ci.parent != null) {
if (ci != null && ci.parent != null && (prop.abc == null || prop.propNsIndex == 0)) {
ci = ci.parent;
//parent protected
DottedChain parentClass = ci.abc.instance_info.get(ci.index).getName(ci.abc.constants).getNameWithNamespace(ci.abc.constants);
@@ -437,7 +449,8 @@ public class AbcIndexing {
map.put(dp, new TraitIndex(t, abc, getTraitReturnType(abc, t), propValue, multinameToType(name_index, abc.constants)));
}
if (mapNs != null) {
PropertyNsDef ndp = new PropertyNsDef(t.getName(abc).getName(abc.constants, new ArrayList<>() /*?*/, true), abc.constants.getMultiname(t.name_index).getNameWithNamespace(abc.constants), abc, abc.constants.getMultiname(t.name_index).namespace_index);
Multiname m = abc.constants.getMultiname(t.name_index);
PropertyNsDef ndp = new PropertyNsDef(t.getName(abc).getName(abc.constants, new ArrayList<>() /*?*/, true), m == null || m.namespace_index == 0 ? DottedChain.EMPTY : m.getNamespace(abc.constants).getName(abc.constants), abc, m.namespace_index);
TraitIndex ti = new TraitIndex(t, abc, getTraitReturnType(abc, t), propValue, multinameToType(name_index, abc.constants));
if (!mapNs.containsKey(ndp)) {
mapNs.put(ndp, ti);

View File

@@ -90,7 +90,6 @@ import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.Loop;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.AndItem;
import com.jpexs.decompiler.graph.model.BinaryOp;
import com.jpexs.decompiler.graph.model.BlockItem;
import com.jpexs.decompiler.graph.model.BreakItem;
import com.jpexs.decompiler.graph.model.CommaExpressionItem;
@@ -181,7 +180,7 @@ public class ActionScript3Parser {
}
ParsedSymbol s = lex();
GraphTargetItem ret = newcmds;
while (s.isType(SymbolType.DOT, SymbolType.PARENT_OPEN, SymbolType.BRACKET_OPEN, SymbolType.TYPENAME, SymbolType.FILTER)) {
while (s.isType(SymbolType.DOT, SymbolType.PARENT_OPEN, SymbolType.BRACKET_OPEN, SymbolType.TYPENAME, SymbolType.FILTER, SymbolType.DESCENDANTS)) {
switch (s.type) {
case BRACKET_OPEN:
case DOT:
@@ -197,6 +196,11 @@ public class ActionScript3Parser {
case PARENT_OPEN:
ret = new CallAVM2Item(lexer.yyline(), ret, call(thisType, pkg, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables));
break;
case DESCENDANTS:
s = lex();
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.MULTIPLY);
ret = new GetDescendantsAVM2Item(ret, s.type == SymbolType.MULTIPLY ? null : s.value.toString(), openedNamespaces);
break;
}
s = lex();
@@ -230,8 +234,13 @@ public class ActionScript3Parser {
if (s.type == SymbolType.TYPENAME) {
List<GraphTargetItem> params = new ArrayList<>();
do {
params.add(expressionPrimary(thisType, pkg, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, false, variables)
);
s = lex();
if (s.isType(SymbolType.MULTIPLY)) {
params.add(new NullAVM2Item(null));
} else {
lexer.pushback(s);
params.add(expressionPrimary(thisType, pkg, needsActivation, importedClasses, openedNamespaces, false, registerVars, inFunction, inMethod, false, variables));
}
s = lex();
} while (s.type == SymbolType.COMMA);
if (s.type == SymbolType.USHIFT_RIGHT) {
@@ -281,8 +290,8 @@ public class ActionScript3Parser {
s = lex();
} else {
s = lex();
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER);
String propName = s.value.toString();
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.MULTIPLY);
String propName = s.value.toString(); //Can be *
GraphTargetItem propItem = null;
s = lex();
GraphTargetItem ns = null;
@@ -351,7 +360,7 @@ public class ActionScript3Parser {
continue;
}
} else {
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.NAMESPACE);
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.NAMESPACE, SymbolType.MULTIPLY);
name2 += s.value.toString();
}
name = name.add(name2);
@@ -455,9 +464,9 @@ public class ActionScript3Parser {
return ret;
}
private MethodAVM2Item method(List<Map.Entry<String, Map<String, String>>> metadata, DottedChain pkg, boolean isInterface, String customAccess, Reference<Boolean> needsActivation, List<DottedChain> importedClasses, boolean override, boolean isFinal, TypeItem thisType, List<Integer> openedNamespaces, boolean isStatic, int namespace, String functionName, boolean isMethod, List<AssignableAVM2Item> variables) throws IOException, AVM2ParseException {
private MethodAVM2Item method(boolean isPrivate, List<Map.Entry<String, Map<String, String>>> metadata, DottedChain pkg, boolean isInterface, String customAccess, Reference<Boolean> needsActivation, List<DottedChain> importedClasses, boolean override, boolean isFinal, TypeItem thisType, List<Integer> openedNamespaces, boolean isStatic, int namespace, String functionName, boolean isMethod, List<AssignableAVM2Item> variables) throws IOException, AVM2ParseException {
FunctionAVM2Item f = function(metadata, pkg, isInterface, needsActivation, importedClasses, namespace, thisType, openedNamespaces, functionName, isMethod, variables);
return new MethodAVM2Item(f.metadata, f.pkg, f.isInterface, customAccess, f.needsActivation, f.hasRest, f.line, override, isFinal, isStatic, f.namespace, functionName, f.paramTypes, f.paramNames, f.paramValues, f.body, f.subvariables, f.retType);
return new MethodAVM2Item(isPrivate, f.metadata, f.pkg, f.isInterface, customAccess, f.needsActivation, f.hasRest, f.line, override, isFinal, isStatic, f.namespace, functionName, f.paramTypes, f.paramNames, f.paramValues, f.body, f.subvariables, f.retType);
}
private FunctionAVM2Item function(List<Map.Entry<String, Map<String, String>>> metadata, DottedChain pkg, boolean isInterface, Reference<Boolean> needsActivation, List<DottedChain> importedClasses, int namespace, TypeItem thisType, List<Integer> openedNamespaces, String functionName, boolean isMethod, List<AssignableAVM2Item> variables) throws IOException, AVM2ParseException {
@@ -550,6 +559,7 @@ public class ActionScript3Parser {
List<Integer> originalOpenedNamespaces = openedNamespaces;
int originalPrivateNs = privateNs;
boolean inPkg = pkg != null;
int cpos = 0;
looptrait:
while (true) {
s = lex();
@@ -561,6 +571,7 @@ public class ActionScript3Parser {
boolean isFinal = false;
boolean isDynamic = false;
String customAccess = null;
boolean isPrivate = false;
if (scriptTraits && s.type == SymbolType.PACKAGE) {
if (inPkg) {
@@ -664,6 +675,7 @@ public class ActionScript3Parser {
}
break;
case PRIVATE:
isPrivate = true;
namespace = privateNs;
if (isInterface) {
throw new AVM2ParseException("Interface cannot have public, private or protected modifier", lexer.yyline());
@@ -685,6 +697,9 @@ public class ActionScript3Parser {
if (isInterface) {
namespace = abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_NAMESPACE, abcIndex.getSelectedAbc().constants.getStringId(pkg == null || pkg.isEmpty() ? classNameStr : pkg + ":" + classNameStr, true)), 0, true);
} else {
if (packageInternalNs == 0) {
packageInternalNs = abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE_INTERNAL, abcIndex.getSelectedAbc().constants.getStringId(pkg.toRawString(), true)), 0, true);
}
namespace = packageInternalNs;
}
}
@@ -785,8 +800,22 @@ public class ActionScript3Parser {
s = lex();
}
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER);
String fname = s.value.toString();
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER, SymbolType.PARENT_OPEN);
String fname = null;
if (s.isType(SymbolType.PARENT_OPEN)) {
lexer.pushback(s);
if (isGetter) {
fname = "get";
isGetter = false;
} else if (isSetter) {
fname = "set";
isSetter = false;
} else {
throw new AVM2ParseException("Missing method name", lexer.yyline());
}
} else {
fname = s.value.toString();
}
if (classNameStr != null && fname.equals(classNameStr)) { //constructor
if (isStatic) {
throw new AVM2ParseException("Constructor cannot be static", lexer.yyline());
@@ -803,9 +832,9 @@ public class ActionScript3Parser {
if (isInterface) {
throw new AVM2ParseException("Interface cannot have constructor", lexer.yyline());
}
constr = (method(metadata, pkg, false, customAccess, new Reference<>(false), importedClasses, false, false, thisType, openedNamespaces, false, namespace, "", true, constrVariables));
constr = (method(isPrivate, metadata, pkg, false, customAccess, new Reference<>(false), importedClasses, false, false, thisType, openedNamespaces, false, namespace, "", true, constrVariables));
} else {
MethodAVM2Item ft = method(metadata, pkg, isInterface, customAccess, new Reference<>(false), importedClasses, isOverride, isFinal, thisType, openedNamespaces, isStatic, namespace, fname, true, new ArrayList<>());
MethodAVM2Item ft = method(isPrivate, metadata, pkg, isInterface, customAccess, new Reference<>(false), importedClasses, isOverride, isFinal, thisType, openedNamespaces, isStatic, namespace, fname, true, new ArrayList<>());
if (isGetter) {
if (!ft.paramTypes.isEmpty()) {
@@ -826,10 +855,10 @@ public class ActionScript3Parser {
}
GraphTargetItem t;
if (isGetter) {
GetterAVM2Item g = new GetterAVM2Item(ft.metadata, ft.pkg, isInterface, customAccess, ft.needsActivation, ft.hasRest, ft.line, ft.isOverride(), ft.isFinal(), isStatic, ft.namespace, ft.functionName, ft.paramTypes, ft.paramNames, ft.paramValues, ft.body, ft.subvariables, ft.retType);
GetterAVM2Item g = new GetterAVM2Item(ft.isPrivate(), ft.metadata, ft.pkg, isInterface, customAccess, ft.needsActivation, ft.hasRest, ft.line, ft.isOverride(), ft.isFinal(), isStatic, ft.namespace, ft.functionName, ft.paramTypes, ft.paramNames, ft.paramValues, ft.body, ft.subvariables, ft.retType);
t = g;
} else if (isSetter) {
SetterAVM2Item st = new SetterAVM2Item(ft.metadata, ft.pkg, isInterface, customAccess, ft.needsActivation, ft.hasRest, ft.line, ft.isOverride(), ft.isFinal(), isStatic, ft.namespace, ft.functionName, ft.paramTypes, ft.paramNames, ft.paramValues, ft.body, ft.subvariables, ft.retType);
SetterAVM2Item st = new SetterAVM2Item(ft.isPrivate(), ft.metadata, ft.pkg, isInterface, customAccess, ft.needsActivation, ft.hasRest, ft.line, ft.isOverride(), ft.isFinal(), isStatic, ft.namespace, ft.functionName, ft.paramTypes, ft.paramNames, ft.paramValues, ft.body, ft.subvariables, ft.retType);
t = st;
} else {
t = ft;
@@ -911,10 +940,15 @@ public class ActionScript3Parser {
break;
default:
if (s.type == SymbolType.CURLY_CLOSE && inPkg && classNameStr == null) {
inPkg = false;
pkg = null;
openedNamespaces = originalOpenedNamespaces;
inPkg = true;
openedNamespaces = new ArrayList<>();
privateNs = originalPrivateNs;
packageInternalNs = originalPrivateNs;
publicNs = privateNs;
//publicNs = abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abcIndex.getSelectedAbc().constants.getStringId("")), 0);
List<Integer> newOpenedNs = new ArrayList<>();
importedClasses = parseImports(newOpenedNs);
pkg = DottedChain.TOPLEVEL;
} else {
lexer.pushback(s);
break looptrait;
@@ -939,8 +973,10 @@ public class ActionScript3Parser {
int publicNs = 0;
int privateNs = 0;
int packageInternalNs = 0;
if (pkg != null) {
if (pkg != null && !pkg.isEmpty()) {
openedNamespaces.add(packageInternalNs = abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE_INTERNAL, abcIndex.getSelectedAbc().constants.getStringId(pkg, true)), 0, true));
} else {
openedNamespaces.add(packageInternalNs = abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE_INTERNAL, abcIndex.getSelectedAbc().constants.getStringId("", true)), 0, true));
}
if (pkg != null && !pkg.isEmpty()) {
openedNamespaces.add(publicNs = abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abcIndex.getSelectedAbc().constants.getStringId("", true)), 0, true));
@@ -948,7 +984,7 @@ public class ActionScript3Parser {
publicNs = gpublicNs;
}
openedNamespaces.add(privateNs = abcIndex.getSelectedAbc().constants.addNamespace(new Namespace(Namespace.KIND_PRIVATE, 0))); //abc.getLastAbc().constants.getStringId(fileName + "$", true)
openedNamespaces.add(privateNs = abcIndex.getSelectedAbc().constants.addNamespace(new Namespace(Namespace.KIND_PRIVATE, abcIndex.getSelectedAbc().constants.getStringId(pkg.toRawString() + ":" + nameStr))));
openedNamespaces.add(abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_NAMESPACE, abcIndex.getSelectedAbc().constants.getStringId(AS3_NAMESPACE, true)), 0, true));
@@ -967,7 +1003,7 @@ public class ActionScript3Parser {
//FIXME for Private classes in script!!!
AVM2SourceGenerator.parentNamesAddNames(abcIndex, AVM2SourceGenerator.resolveType(new SourceGeneratorLocalData(new HashMap<>(), 0, false, 0), ((TypeItem) ((UnresolvedAVM2Item) extendsStr).resolve(null, new ArrayList<>(), new ArrayList<>(), abcIndex, new ArrayList<>(), new ArrayList<>())), abcIndex), indices, names, namespaces);
for (int i = 0; i < names.size(); i++) {
if (namespaces.get(i).isEmpty()) {
if (namespaces.get(i) == null || namespaces.get(i).isEmpty()) {
continue;
}
openedNamespaces.add(abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_STATIC_PROTECTED, abcIndex.getSelectedAbc().constants.getStringId(namespaces.get(i) + ":" + names.get(i), true)), 0, true));
@@ -1444,10 +1480,16 @@ public class ActionScript3Parser {
GraphTargetItem forExpr = null;
List<GraphTargetItem> forFirstCommands = new ArrayList<>();
if (!forin) {
//GraphTargetItem firstCommand = command(thisType,pkg,needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables);
s = lex();
if (firstCommand != null) { //can be empty command
forFirstCommands.add(firstCommand);
}
while (s.isType(SymbolType.COMMA)) {
forFirstCommands.add(command(thisType, pkg, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, false, variables));
s = lex();
}
lexer.pushback(s);
//GraphTargetItem firstCommand = command(thisType,pkg,needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables);
forExpr = (expression(thisType, pkg, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, true, variables));
expectedType(SymbolType.SEMICOLON);
GraphTargetItem fcom = command(thisType, pkg, needsActivation, importedClasses, openedNamespaces, loops, loopLabels, registerVars, inFunction, inMethod, forinlevel, true, variables);
@@ -2132,6 +2174,7 @@ public class ActionScript3Parser {
List<GraphTargetItem> inBrackets = new ArrayList<>();
int arrCnt = brackets(thisType, pkg, needsActivation, importedClasses, openedNamespaces, inBrackets, registerVars, inFunction, inMethod, variables);
ret = new NewArrayAVM2Item(null, inBrackets);
allowMemberOrCall = true;
break;
case FUNCTION:
@@ -2270,24 +2313,9 @@ public class ActionScript3Parser {
private List<String> constantPool;
private PackageAVM2Item parsePackage(List<Integer> openedNamespaces) throws IOException, AVM2ParseException, CompilationException {
List<GraphTargetItem> items = new ArrayList<>();
expectedType(SymbolType.PACKAGE);
DottedChain name = DottedChain.TOPLEVEL;
ParsedSymbol s = lex();
if (s.type != SymbolType.CURLY_OPEN) {
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER);
name = name.add(s.value.toString());
s = lex();
}
while (s.type != SymbolType.CURLY_OPEN) {
expected(s, lexer.yyline(), SymbolType.DOT);
s = lex();
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER);
name = name.add(s.value.toString());
s = lex();
}
private List<DottedChain> parseImports(List<Integer> openedNamespaces) throws IOException, AVM2ParseException {
ParsedSymbol s;
List<DottedChain> importedClasses = new ArrayList<>();
s = lex();
@@ -2322,7 +2350,28 @@ public class ActionScript3Parser {
s = lex();
}
lexer.pushback(s);
return importedClasses;
}
private PackageAVM2Item parsePackage(List<Integer> openedNamespaces) throws IOException, AVM2ParseException, CompilationException {
List<GraphTargetItem> items = new ArrayList<>();
expectedType(SymbolType.PACKAGE);
DottedChain name = DottedChain.TOPLEVEL;
ParsedSymbol s = lex();
if (s.type != SymbolType.CURLY_OPEN) {
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER);
name = name.add(s.value.toString());
s = lex();
}
while (s.type != SymbolType.CURLY_OPEN) {
expected(s, lexer.yyline(), SymbolType.DOT);
s = lex();
expected(s, lexer.yyline(), SymbolGroup.IDENTIFIER);
name = name.add(s.value.toString());
s = lex();
}
List<DottedChain> importedClasses = parseImports(openedNamespaces);
int publicNs;
openedNamespaces.add(publicNs = abcIndex.getSelectedAbc().constants.getNamespaceId(new Namespace(Namespace.KIND_PACKAGE, abcIndex.getSelectedAbc().constants.getStringId(name, true)), 0, true));

View File

@@ -27,7 +27,7 @@ import java.util.Map;
*/
public class GetterAVM2Item extends MethodAVM2Item {
public GetterAVM2Item(List<Map.Entry<String, Map<String, String>>> metadata, DottedChain pkg, boolean isInterface, String customNamespace, boolean needsActivation, boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, List<AssignableAVM2Item> subvariables, GraphTargetItem retType) {
super(metadata, pkg, isInterface, customNamespace, needsActivation, hasRest, line, override, isFinal, isStatic, namespace, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType);
public GetterAVM2Item(boolean isPrivate, List<Map.Entry<String, Map<String, String>>> metadata, DottedChain pkg, boolean isInterface, String customNamespace, boolean needsActivation, boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, List<AssignableAVM2Item> subvariables, GraphTargetItem retType) {
super(isPrivate, metadata, pkg, isInterface, customNamespace, needsActivation, hasRest, line, override, isFinal, isStatic, namespace, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType);
}
}

View File

@@ -35,14 +35,21 @@ public class MethodAVM2Item extends FunctionAVM2Item {
private final boolean override;
private final boolean isPrivate;
public boolean isPrivate() {
return isPrivate;
}
public String customNamespace;
//public boolean isInterface;
public MethodAVM2Item(List<Map.Entry<String, Map<String, String>>> metadata, DottedChain pkg, boolean isInterface, String customNamespace, boolean needsActivation, boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, List<AssignableAVM2Item> subvariables, GraphTargetItem retType) {
public MethodAVM2Item(boolean isPrivate, List<Map.Entry<String, Map<String, String>>> metadata, DottedChain pkg, boolean isInterface, String customNamespace, boolean needsActivation, boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, List<AssignableAVM2Item> subvariables, GraphTargetItem retType) {
super(metadata, pkg, isInterface, needsActivation, namespace, hasRest, line, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType);
this.isStatic = isStatic;
this.override = override;
this.isFinal = isFinal;
this.isPrivate = isPrivate;
this.customNamespace = customNamespace;
//this.isInterface = this.isInterface;
}

View File

@@ -27,7 +27,7 @@ import java.util.Map;
*/
public class SetterAVM2Item extends MethodAVM2Item {
public SetterAVM2Item(List<Map.Entry<String, Map<String, String>>> metadata, DottedChain pkg, boolean isInterface, String customNamespace, boolean needsActivation, boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, List<AssignableAVM2Item> subvariables, GraphTargetItem retType) {
super(metadata, pkg, isInterface, customNamespace, needsActivation, hasRest, line, override, isFinal, isStatic, namespace, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType);
public SetterAVM2Item(boolean isPrivate, List<Map.Entry<String, Map<String, String>>> metadata, DottedChain pkg, boolean isInterface, String customNamespace, boolean needsActivation, boolean hasRest, int line, boolean override, boolean isFinal, boolean isStatic, int namespace, String methodName, List<GraphTargetItem> paramTypes, List<String> paramNames, List<GraphTargetItem> paramValues, List<GraphTargetItem> body, List<AssignableAVM2Item> subvariables, GraphTargetItem retType) {
super(isPrivate, metadata, pkg, isInterface, customNamespace, needsActivation, hasRest, line, override, isFinal, isStatic, namespace, methodName, paramTypes, paramNames, paramValues, body, subvariables, retType);
}
}

View File

@@ -110,7 +110,7 @@ public abstract class Trait implements Cloneable, Serializable {
writer.append(",");
}
first = false;
if (!key.isEmpty()) {
if (key != null && !key.isEmpty()) {
writer.append(IdentifiersDeobfuscation.printIdentifier(true, key)).append("=");
}
writer.append("\"");
@@ -248,7 +248,7 @@ public abstract class Trait implements Cloneable, Serializable {
public final ClassPath getPath(ABC abc) {
Multiname name = getName(abc);
Namespace ns = name.getNamespace(abc.constants);
DottedChain packageName = ns.getName(abc.constants);
DottedChain packageName = ns == null ? DottedChain.EMPTY : ns.getName(abc.constants);
String objectName = name.getName(abc.constants, null, true);
return new ClassPath(packageName, objectName); //assume not null name
}

View File

@@ -157,6 +157,10 @@ public class Graph {
cur1.iloop_header = cur2;
}
protected List<GraphTargetItem> filter(List<GraphTargetItem> list) {
return new ArrayList<>(list);
}
/**
* Traverse loops deep first search
*
@@ -1989,20 +1993,26 @@ public class Graph {
makeAllCommands(onTrue, trueStack);
makeAllCommands(onFalse, falseStack);
if (!isEmpty(onTrue) && !isEmpty(onFalse) && onTrue.size() == 1 && onFalse.size() == 1 && (onTrue.get(0) instanceof PushItem) && (onFalse.get(0) instanceof PushItem)) {
stack.push(new TernarOpItem(null, expr.invert(null), ((PushItem) onTrue.get(0)).value, ((PushItem) onFalse.get(0)).value));
List<GraphTargetItem> filteredOnTrue = filter(onTrue);
List<GraphTargetItem> filteredOnFalse = filter(onFalse);
if (!isEmpty(filteredOnTrue) && !isEmpty(filteredOnFalse) && filteredOnTrue.size() == 1 && filteredOnFalse.size() == 1 && (filteredOnTrue.get(0) instanceof PushItem) && (filteredOnFalse.get(0) instanceof PushItem)) {
stack.push(new TernarOpItem(null, expr.invert(null), ((PushItem) filteredOnTrue.get(0)).value, ((PushItem) filteredOnFalse.get(0)).value));
} else {
boolean isIf = true;
//If the ontrue is empty, switch ontrue and onfalse
if (onTrue.isEmpty() && !onFalse.isEmpty()) {
if (filteredOnTrue.isEmpty() && !filteredOnFalse.isEmpty()) {
expr = expr.invert(null);
List<GraphTargetItem> tmp = onTrue;
onTrue = onFalse;
onFalse = tmp;
tmp = filteredOnTrue;
filteredOnTrue = filteredOnFalse;
filteredOnFalse = tmp;
}
if (!stack.isEmpty() && onFalse.isEmpty() && ((onTrue.size() == 1 && (onTrue.get(0) instanceof PopItem)) || ((onTrue.size() == 2) && (onTrue.get(0) instanceof PopItem) && (onTrue.get(1) instanceof PushItem)))) {
if (onTrue.size() == 2) {
GraphTargetItem rightSide = ((PushItem) onTrue.get(1)).value;
if (!stack.isEmpty() && ((filteredOnTrue.size() == 1 && (filteredOnTrue.get(0) instanceof PopItem)) || ((filteredOnTrue.size() >= 2) && (filteredOnTrue.get(0) instanceof PopItem) && (filteredOnTrue.get(filteredOnTrue.size() - 1) instanceof PushItem)))) {
if (filteredOnTrue.size() > 1) {
GraphTargetItem rightSide = ((PushItem) filteredOnTrue.get(filteredOnTrue.size() - 1)).value;
GraphTargetItem prevExpr = stack.pop();
GraphTargetItem leftSide = expr.getNotCoercedNoDup();