Resolving return type for properties, local regs, function calls.

This commit is contained in:
Jindra Petřík
2022-11-25 18:45:22 +01:00
parent 25aa987cdf
commit 727c076e05
22 changed files with 246 additions and 78 deletions

View File

@@ -419,6 +419,27 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
}
public AbcIndexing getAbcIndex() {
if (abcIndex != null) {
return abcIndex;
}
boolean air = false;
SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(getShortPathTitle());
if (conf != null) {
if (conf.getCustomData(CustomConfigurationKeys.KEY_LIBRARY, "" + LIBRARY_FLASH).equals("" + LIBRARY_AIR)) {
air = true;
}
}
try {
SWF.initPlayer();
} catch (IOException | InterruptedException ex) {
Logger.getLogger(SWF.class.getName()).log(Level.SEVERE, null, ex);
}
abcIndex = new AbcIndexing(air ? SWF.getAirGlobalAbcIndex() : SWF.getPlayerGlobalAbcIndex());
for (Tag tag:tags) {
if (tag instanceof ABCContainerTag) {
abcIndex.addAbc(((ABCContainerTag)tag).getABC());
}
}
return abcIndex;
}
@@ -1460,21 +1481,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
clearScriptCache();
}
getASMs(true); // Add scriptNames to ASMs
boolean air = false;
SwfSpecificCustomConfiguration conf = Configuration.getSwfSpecificCustomConfiguration(getShortPathTitle());
if (conf != null) {
if (conf.getCustomData(CustomConfigurationKeys.KEY_LIBRARY, "" + LIBRARY_FLASH).equals("" + LIBRARY_AIR)) {
air = true;
}
}
abcIndex = new AbcIndexing(air ? SWF.getAirGlobalAbcIndex() : SWF.getPlayerGlobalAbcIndex());
for (Tag tag:tags) {
if (tag instanceof ABCContainerTag) {
abcIndex.addAbc(((ABCContainerTag)tag).getABC());
}
}
getASMs(true); // Add scriptNames to ASMs
}
private void resolveImported(UrlResolver resolver) {
@@ -3090,7 +3097,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
}
}
return decompilerPool.decompile(swf.abcIndex, pack);
return decompilerPool.decompile(swf.getAbcIndex(), pack);
}
public static Future<HighlightedText> getCachedFuture(ASMSource src, ActionList actions, ScriptDecompiledListener<HighlightedText> listener) throws InterruptedException {
@@ -3125,7 +3132,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
}
}
return decompilerPool.submitTask(swf.abcIndex, pack, listener);
return decompilerPool.submitTask(swf.getAbcIndex(), pack, listener);
}
public DecompilerPool getDecompilerPool() {
@@ -4036,7 +4043,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
int mi = ((TraitMethodGetterSetter) t).method_info;
try {
documentPack.abc.findBody(mi).convert(abcIndex, new ConvertData(), "??", ScriptExportMode.AS, true, mi, documentPack.scriptIndex, cindex, documentPack.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>());
documentPack.abc.findBody(mi).convert(getAbcIndex(), new ConvertData(), "??", ScriptExportMode.AS, true, mi, documentPack.scriptIndex, cindex, documentPack.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>());
List<GraphTargetItem> infos = documentPack.abc.findBody(mi).convertedItems;
if (!infos.isEmpty()) {
if (infos.get(0) instanceof IfItem) {
@@ -4112,7 +4119,7 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
if (tr instanceof TraitClass) {
int ci = ((TraitClass) tr).class_info;
int cinit = p.abc.class_info.get(ci).cinit_index;
p.abc.findBody(cinit).convert(abcIndex, new ConvertData(), "??", ScriptExportMode.AS, true, cinit, p.scriptIndex, cindex, p.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>());
p.abc.findBody(cinit).convert(getAbcIndex(), new ConvertData(), "??", ScriptExportMode.AS, true, cinit, p.scriptIndex, cindex, p.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>());
List<GraphTargetItem> cinitBody = p.abc.findBody(cinit).convertedItems;
for (GraphTargetItem cit : cinitBody) {
if (cit instanceof SetPropertyAVM2Item) {

View File

@@ -58,6 +58,8 @@ public class AVM2LocalData extends BaseLocalData {
public AbcIndexing abcIndex;
public HashMap<Integer, String> localRegNames;
public HashMap<Integer, GraphTargetItem> localRegTypes;
public List<DottedChain> fullyQualifiedNames;
@@ -146,6 +148,7 @@ public class AVM2LocalData extends BaseLocalData {
abc = localData.abc;
abcIndex = localData.abcIndex;
localRegNames = localData.localRegNames;
localRegTypes = localData.localRegTypes;
fullyQualifiedNames = localData.fullyQualifiedNames;
parsedExceptions = localData.parsedExceptions;
finallyJumps = localData.finallyJumps;

View File

@@ -1589,7 +1589,7 @@ public class AVM2Code implements Cloneable {
return pos2adr(getIpThroughJumpAndDebugLine(adr2pos(addr, true)));
}
public ConvertOutput toSourceOutput(Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws ConvertException, InterruptedException {
public ConvertOutput toSourceOutput(AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, boolean thisHasDefaultToPrimitive, Reference<GraphSourceItem> lineStartItem, String path, GraphPart part, boolean processJumps, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, ABC abc, MethodBody body, int start, int end, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, boolean[] visited, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs) throws ConvertException, InterruptedException {
calcKilledStats(body);
boolean debugMode = DEBUG_MODE;
if (debugMode) {
@@ -1664,7 +1664,7 @@ public class AVM2Code implements Cloneable {
do {
AVM2Instruction insAfter = ip + 1 < code.size() ? code.get(ip + 1) : null;
if (insAfter == null) {
ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
ins.definition.translate(abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
ip++;
break;
}
@@ -1686,14 +1686,14 @@ public class AVM2Code implements Cloneable {
//stack.add("(" + stack.pop() + ")||");
isAnd = false;
} else {
ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
ins.definition.translate(abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
ip++;
break;
//throw new ConvertException("Unknown pattern after DUP:" + insComparsion.toString());
}
} while (ins.definition instanceof DupIns);
} else if ((ins.definition instanceof ReturnValueIns) || (ins.definition instanceof ReturnVoidIns) || (ins.definition instanceof ThrowIns)) {
ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
ins.definition.translate(abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
//ip = end + 1;
break;
} else if (ins.definition instanceof NewFunctionIns) {
@@ -1729,13 +1729,13 @@ public class AVM2Code implements Cloneable {
}
}
// What to do when hasDup is false?
ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
ins.definition.translate(abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
NewFunctionAVM2Item nft = (NewFunctionAVM2Item) stack.peek();
nft.functionName = functionName;
ip++;
} else {
try {
ins.definition.translate(setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
ins.definition.translate(abcIndex, setLocalPosToGetLocalPos, lineStartItem, isStatic, scriptIndex, classIndex, localRegs, stack, scopeStack, ins, output, body, abc, localRegNames, localRegTypes, fullyQualifiedNames, path, localRegAssigmentIps, ip, refs, this, thisHasDefaultToPrimitive);
} catch (RuntimeException re) {
/*String last="";
int len=5;
@@ -2136,9 +2136,13 @@ public class AVM2Code implements Cloneable {
for (int i = 0; i < regCount; i++) {
localRegs.put(0, new UndefinedAVM2Item(null, null));
}
HashMap<Integer, GraphTargetItem> localRegTypes = new HashMap<>();
for (int i = 0; i < abc.method_info.get(methodIndex).param_types.length; i++) {
localRegTypes.put(i + 1, PropertyAVM2Item.multinameToType(abc.method_info.get(methodIndex).param_types[i], abc.constants));
}
//try {
list = AVM2Graph.translateViaGraph(abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs, thisHasDefaultToPrimitive);
list = AVM2Graph.translateViaGraph(abcIndex, path, this, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, localRegTypes, fullyQualifiedNames, staticOperation, localRegAssigmentIps, refs, thisHasDefaultToPrimitive);
if (initTraits != null) {
loopi:

View File

@@ -112,6 +112,7 @@ public class AVM2DeobfuscatorGetSet extends SWFDecompilerAdapter {
localData.methodBody = body;
localData.abc = abc;
localData.localRegNames = new HashMap<>();
localData.localRegTypes = new HashMap<>();
localData.scriptIndex = scriptIndex;
localData.ip = 0;
localData.code = body.getCode();

View File

@@ -202,6 +202,7 @@ public class AVM2DeobfuscatorSimpleOld extends AVM2DeobfuscatorZeroJumpsNullPush
localData.methodBody = body;
localData.abc = abc;
localData.localRegNames = new HashMap<>();
localData.localRegTypes = new HashMap<>();
localData.scriptIndex = scriptIndex;
localData.ip = 0;
localData.code = body.getCode();

View File

@@ -633,7 +633,7 @@ public class AVM2Graph extends Graph {
return setLocalPosToGetLocalPos;
}
public static List<GraphTargetItem> translateViaGraph(AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, int staticOperation, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs, boolean thisHasDefaultToPrimitive) throws InterruptedException {
public static List<GraphTargetItem> translateViaGraph(AbcIndexing abcIndex, String path, AVM2Code code, ABC abc, MethodBody body, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, ScopeStack scopeStack, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, int staticOperation, HashMap<Integer, Integer> localRegAssigmentIps, HashMap<Integer, List<Integer>> refs, boolean thisHasDefaultToPrimitive) throws InterruptedException {
AVM2Graph g = new AVM2Graph(abcIndex, code, abc, body, isStatic, scriptIndex, classIndex, localRegs, scopeStack, localRegNames, fullyQualifiedNames, localRegAssigmentIps, refs);
AVM2LocalData localData = new AVM2LocalData();
@@ -644,7 +644,9 @@ public class AVM2Graph extends Graph {
localData.scopeStack = scopeStack;
localData.methodBody = body;
localData.abc = abc;
localData.abcIndex = abcIndex;
localData.localRegNames = localRegNames;
localData.localRegTypes = localRegTypes;
localData.fullyQualifiedNames = fullyQualifiedNames;
localData.scriptIndex = scriptIndex;
localData.ip = 0;
@@ -1505,11 +1507,11 @@ public class AVM2Graph extends Graph {
List<GraphTargetItem> otherSide = new ArrayList<>();
if (leftReg > 0) {
switchedObject = new LocalRegAVM2Item(null, null, leftReg, null);
switchedObject = new LocalRegAVM2Item(null, null, leftReg, null, TypeItem.UNBOUNDED /*?*/);
caseValuesMap = caseValuesMapRight;
otherSide = caseValuesMapLeft;
} else if (rightReg > 0) {
switchedObject = new LocalRegAVM2Item(null, null, rightReg, null);
switchedObject = new LocalRegAVM2Item(null, null, rightReg, null, TypeItem.UNBOUNDED /*?*/);
otherSide = caseValuesMapRight;
}

View File

@@ -119,7 +119,7 @@ public class AVM2GraphSource extends GraphSource {
List<GraphTargetItem> ret = new ArrayList<>();
ScopeStack newstack = ((AVM2LocalData) localData).scopeStack;
Reference<GraphSourceItem> lineStartItem = new Reference<>(localData.lineStartInstruction);
ConvertOutput co = code.toSourceOutput(((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, body, start, end, localRegNames, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, refs);
ConvertOutput co = code.toSourceOutput(((AVM2LocalData) localData).abcIndex, ((AVM2LocalData) localData).setLocalPosToGetLocalPos, ((AVM2LocalData) localData).thisHasDefaultToPrimitive, lineStartItem, path, part, false, isStatic, scriptIndex, classIndex, localRegs, stack, newstack, abc, body, start, end, localRegNames, ((AVM2LocalData) localData).localRegTypes, fullyQualifiedNames, new boolean[size()], localRegAssigmentIps, refs);
localData.lineStartInstruction = lineStartItem.getVal();
ret.addAll(co.output);
return ret;

View File

@@ -36,6 +36,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.ThisAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
@@ -170,7 +171,7 @@ public abstract class InstructionDefinition implements Serializable {
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, String path) throws InterruptedException {
}
public void translate(Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, Reference<GraphSourceItem> lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2Instruction ins, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code, boolean thisHasDefaultToPrimitive) throws InterruptedException {
public void translate(AbcIndexing abcIndex, Map<Integer, Set<Integer>> setLocalPosToGetLocalPos, Reference<GraphSourceItem> lineStartItem, boolean isStatic, int scriptIndex, int classIndex, HashMap<Integer, GraphTargetItem> localRegs, TranslateStack stack, ScopeStack scopeStack, AVM2Instruction ins, List<GraphTargetItem> output, MethodBody body, ABC abc, HashMap<Integer, String> localRegNames, HashMap<Integer, GraphTargetItem> localRegTypes, List<DottedChain> fullyQualifiedNames, String path, HashMap<Integer, Integer> localRegsAssignmentIps, int ip, HashMap<Integer, List<Integer>> refs, AVM2Code code, boolean thisHasDefaultToPrimitive) throws InterruptedException {
AVM2LocalData localData = new AVM2LocalData();
localData.isStatic = isStatic;
localData.scriptIndex = scriptIndex;
@@ -180,7 +181,9 @@ public abstract class InstructionDefinition implements Serializable {
localData.scopeStack = scopeStack;
localData.methodBody = body;
localData.abc = abc;
localData.abcIndex = abcIndex;
localData.localRegNames = localRegNames;
localData.localRegTypes = localRegTypes;
localData.fullyQualifiedNames = fullyQualifiedNames;
localData.localRegAssignmentIps = localRegsAssignmentIps;
localData.ip = ip;

View File

@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.DuplicateItem;
import java.util.List;
@@ -59,7 +60,7 @@ public interface SetTypeIns {
result.value = value;
output.add(result);
for (int i = 0; i < numDups; i++) {
stack.push(new LocalRegAVM2Item(null, localData.lineStartInstruction, regId, value));
stack.push(new LocalRegAVM2Item(null, localData.lineStartInstruction, regId, value, localData.localRegTypes.containsKey(regId) ? localData.localRegTypes.get(regId) : TypeItem.UNBOUNDED));
}
return;
} else {
@@ -74,7 +75,7 @@ public interface SetTypeIns {
if (regId > -1 && AVM2Item.mustStayIntact2(insideDup.getNotCoerced())) { //hack
output.add(result);
stack.push(new LocalRegAVM2Item(null, localData.lineStartInstruction, regId, value));
stack.push(new LocalRegAVM2Item(null, localData.lineStartInstruction, regId, value, localData.localRegTypes.containsKey(regId) ? localData.localRegTypes.get(regId) : TypeItem.UNBOUNDED));
return;
}

View File

@@ -96,6 +96,13 @@ public class CallPropLexIns extends CallPropertyIns {
break;
}
}
} else {
if (localData.abcIndex != null) {
GraphTargetItem receiverType = receiver.returnType();
if (!receiverType.equals(TypeItem.UNBOUNDED)) {
type = localData.abcIndex.findPropertyCallType(localData.abc, receiverType, multiname.resolvedMultinameName, localData.abc.constants.getMultiname(multinameIndex).namespace_index,true, true);
}
}
}
stack.push(new CallPropertyAVM2Item(ins, localData.lineStartInstruction, false, receiver, multiname, args, type));

View File

@@ -96,6 +96,13 @@ public class CallPropVoidIns extends InstructionDefinition {
break;
}
}
} else {
if (localData.abcIndex != null) {
GraphTargetItem receiverType = receiver.returnType();
if (!receiverType.equals(TypeItem.UNBOUNDED)) {
type = localData.abcIndex.findPropertyCallType(localData.abc, receiverType, multiname.resolvedMultinameName, localData.abc.constants.getMultiname(multinameIndex).namespace_index,true, true);
}
}
}
output.add(new CallPropertyAVM2Item(ins, localData.lineStartInstruction, true, receiver, multiname, args, type));
}

View File

@@ -93,9 +93,16 @@ public class CallPropertyIns extends InstructionDefinition {
case "Number":
case "String":
type = new TypeItem(multiname.resolvedMultinameName);
break;
break;
}
}
} else {
if (localData.abcIndex != null) {
GraphTargetItem receiverType = receiver.returnType();
if (!receiverType.equals(TypeItem.UNBOUNDED)) {
type = localData.abcIndex.findPropertyCallType(localData.abc, receiverType, multiname.resolvedMultinameName, localData.abc.constants.getMultiname(multinameIndex).namespace_index,true, true);
}
}
}
stack.push(new CallPropertyAVM2Item(ins, localData.lineStartInstruction, false, receiver, multiname, args, type));
}

View File

@@ -43,6 +43,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.ecma.Undefined;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.DuplicateItem;
import java.util.List;
@@ -167,8 +168,14 @@ public abstract class GetLocalTypeIns extends InstructionDefinition {
}
}
}
stack.push(new LocalRegAVM2Item(ins, localData.lineStartInstruction, regId, computedValue));
GraphTargetItem type = TypeItem.UNBOUNDED;
if (localData.localRegTypes.containsKey(regId)) {
type = localData.localRegTypes.get(regId);
} else if (computedValue != null) {
type = computedValue.returnType();
}
stack.push(new LocalRegAVM2Item(ins, localData.lineStartInstruction, regId, computedValue, type));
}
@Override

View File

@@ -27,7 +27,6 @@ import com.jpexs.decompiler.flash.abc.avm2.parser.script.PropertyAVM2Item;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.decompiler.graph.TypeItem;
@@ -50,7 +49,7 @@ public class GetLexIns extends InstructionDefinition {
int multinameIndex = ins.operands[0];
Multiname multiname = localData.getConstants().getMultiname(multinameIndex);
String multinameStr = multiname.getName(localData.abc.constants, new ArrayList<>(), true, true);
GraphTargetItem slotType = TypeItem.UNBOUNDED;
GraphTargetItem slotType = null;
for (Trait t : localData.methodBody.traits.traits) {
if (t instanceof TraitSlotConst) {
TraitSlotConst tsc = (TraitSlotConst) t;
@@ -63,6 +62,27 @@ public class GetLexIns extends InstructionDefinition {
}
}
}
if (slotType == null) {
if (localData.abcIndex != null) {
String currentClassName = localData.classIndex == -1 ? null : localData.abc.instance_info.get(localData.classIndex).getName(localData.abc.constants).getNameWithNamespace(localData.abc.constants, true).toRawString();
GraphTargetItem thisPropType = currentClassName == null ? TypeItem.UNBOUNDED : localData.abcIndex.findPropertyType(localData.abc, new TypeItem(currentClassName), multinameStr, localData.abc.constants.getMultiname(multinameIndex).namespace_index, true, true);
if (!thisPropType.equals(TypeItem.UNBOUNDED)) {
slotType = thisPropType;
}
if (slotType == null) {
TypeItem ti = new TypeItem(multiname.getNameWithNamespace(localData.abc.constants, true));
if (localData.abcIndex.findClass(ti) != null) {
slotType = ti;
}
}
}
}
if (slotType == null) {
slotType = TypeItem.UNBOUNDED;
}
stack.push(new GetLexAVM2Item(ins, localData.lineStartInstruction, multiname, localData.getConstants(), slotType));
}

View File

@@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.GetLexAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.GetPropertyAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item;
@@ -128,22 +129,55 @@ public class GetPropertyIns extends InstructionDefinition {
}
}
GraphTargetItem propertyType = TypeItem.UNBOUNDED;
GraphTargetItem type = null;
String multinameStr = localData.abc.constants.getMultiname(multiname.multinameIndex).getName(localData.abc.constants, new ArrayList<>(), true, true);
for (Trait t : localData.methodBody.traits.traits) {
if (t instanceof TraitSlotConst) {
TraitSlotConst tsc = (TraitSlotConst) t;
if (Objects.equals(
tsc.getName(localData.abc).getName(localData.abc.constants, new ArrayList<>(), true, true),
multinameStr
)) {
propertyType = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants);
break;
if (obj instanceof FindPropertyAVM2Item) {
FindPropertyAVM2Item fprop = (FindPropertyAVM2Item) obj;
if (fprop.propertyName.equals(multiname)) {
for (Trait t : localData.methodBody.traits.traits) {
if (t instanceof TraitSlotConst) {
TraitSlotConst tsc = (TraitSlotConst) t;
if (Objects.equals(
tsc.getName(localData.abc).getName(localData.abc.constants, new ArrayList<>(), true, true),
multinameStr
)) {
type = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants);
break;
}
}
}
if (type == null) {
if (localData.abcIndex != null) {
String currentClassName = localData.classIndex == -1 ? null : localData.abc.instance_info.get(localData.classIndex).getName(localData.abc.constants).getNameWithNamespace(localData.abc.constants, true).toRawString();
GraphTargetItem thisPropType = currentClassName == null ? TypeItem.UNBOUNDED : localData.abcIndex.findPropertyType(localData.abc, new TypeItem(currentClassName), multinameStr, localData.abc.constants.getMultiname(multinameIndex).namespace_index, true, true);
if (!thisPropType.equals(TypeItem.UNBOUNDED)) {
type = thisPropType;
}
if (type == null) {
TypeItem ti = new TypeItem(localData.abc.constants.getMultiname(multinameIndex).getNameWithNamespace(localData.abc.constants, true));
if (localData.abcIndex.findClass(ti) != null) {
type = ti;
}
}
}
}
}
} else {
if (localData.abcIndex != null) {
GraphTargetItem receiverType = obj.returnType();
if (!receiverType.equals(TypeItem.UNBOUNDED)) {
type = localData.abcIndex.findPropertyType(localData.abc, receiverType, multiname.resolvedMultinameName, localData.abc.constants.getMultiname(multinameIndex).namespace_index,true, true);
}
}
}
stack.push(new GetPropertyAVM2Item(ins, localData.lineStartInstruction, obj, multiname, propertyType));
if (type == null) {
type = TypeItem.UNBOUNDED;
}
stack.push(new GetPropertyAVM2Item(ins, localData.lineStartInstruction, obj, multiname, type));
}
@Override

View File

@@ -25,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.HasNextAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.decompiler.graph.TypeItem;
import java.util.List;
/**
@@ -43,8 +44,8 @@ public class HasNext2Ins extends InstructionDefinition {
int indexReg = ins.operands[1];
//stack.push("_loc_" + objectReg + ".hasNext(cnt=_loc_" + indexReg + ")");
stack.push(new HasNextAVM2Item(ins, localData.lineStartInstruction,
new LocalRegAVM2Item(ins, localData.lineStartInstruction, indexReg, localData.localRegs.get(indexReg)),
new LocalRegAVM2Item(ins, localData.lineStartInstruction, objectReg, localData.localRegs.get(objectReg))
new LocalRegAVM2Item(ins, localData.lineStartInstruction, indexReg, localData.localRegs.get(indexReg), TypeItem.UNBOUNDED /*?*/),
new LocalRegAVM2Item(ins, localData.lineStartInstruction, objectReg, localData.localRegs.get(objectReg), TypeItem.UNBOUNDED /*?*/)
));
}

View File

@@ -40,11 +40,13 @@ public class LocalRegAVM2Item extends AVM2Item {
public GraphTargetItem computedValue;
public GraphTargetItem type;
private final Object computedResult;
private boolean isCT = false;
private boolean isCT = false;
public LocalRegAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, int regIndex, GraphTargetItem computedValue) {
public LocalRegAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, int regIndex, GraphTargetItem computedValue, GraphTargetItem type) {
super(instruction, lineStartIns, PRECEDENCE_PRIMARY);
this.regIndex = regIndex;
if (computedValue == null) {
@@ -56,6 +58,7 @@ public class LocalRegAVM2Item extends AVM2Item {
computedResult = null;
}
this.computedValue = computedValue;
this.type = type;
}
@Override
@@ -131,10 +134,7 @@ public class LocalRegAVM2Item extends AVM2Item {
@Override
public GraphTargetItem returnType() {
if (computedValue != null) {
return computedValue.returnType();
}
return TypeItem.UNBOUNDED;
return type;
}
@Override

View File

@@ -80,7 +80,7 @@ public class SetLocalAVM2Item extends AVM2Item implements SetTypeAVM2Item, Assig
@Override
public GraphTargetItem getObject() {
return new LocalRegAVM2Item(getInstruction(), getLineStartIns(), regIndex, null);
return new LocalRegAVM2Item(getInstruction(), getLineStartIns(), regIndex, null, value.returnType());
}
@Override

View File

@@ -95,7 +95,7 @@ public class ThisAVM2Item extends AVM2Item {
@Override
public GraphTargetItem returnType() {
return TypeItem.UNBOUNDED;
return new TypeItem(className);
}
@Override

View File

@@ -324,7 +324,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
AssignableAVM2Item.dupSetTemp(localData, this, tempVal2),
ins(AVM2Instructions.PushWith)
));
localData.scopeStack.add(new LocalRegAVM2Item(null, null, tempVal2.getVal(), null));
localData.scopeStack.add(new LocalRegAVM2Item(null, null, tempVal2.getVal(), null, new TypeItem("Object") /*?*/));
forBody.addAll(toInsList(item.value.toSource(localData, this)));
List<AVM2Instruction> trueBody = new ArrayList<>();
trueBody.addAll(toInsList(AssignableAVM2Item.getTemp(localData, this, xmlListReg)));
@@ -547,7 +547,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
ret.addAll(item.scope.toSource(localData, this));
Reference<Integer> tempReg = new Reference<>(0);
ret.addAll(AssignableAVM2Item.dupSetTemp(localData, this, tempReg));
localData.scopeStack.add(new WithObjectAVM2Item(null, null, new LocalRegAVM2Item(null, null, tempReg.getVal(), null)));
localData.scopeStack.add(new WithObjectAVM2Item(null, null, new LocalRegAVM2Item(null, null, tempReg.getVal(), null, new TypeItem("Object") /*?*/)));
ret.add(ins(AVM2Instructions.PushWith));
ret.addAll(generate(localData, item.items));
ret.add(ins(AVM2Instructions.PopScope));
@@ -842,7 +842,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
}
}
localData.catchesTempRegs.add(tempReg.getVal());
localData.scopeStack.add(new LocalRegAVM2Item(null, null, tempReg.getVal(), null));
localData.scopeStack.add(new LocalRegAVM2Item(null, null, tempReg.getVal(), null, new TypeItem("Object") /*?*/));
localData.catchesOpenedLoops.add(new ArrayList<>(localData.openedLoops));
catchCmd.addAll(generateToInsList(localData, item.catchCommands.get(c)));
localData.catchesOpenedLoops.remove(localData.catchesOpenedLoops.size() - 1);
@@ -1657,7 +1657,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
if (className != null) {
String fullClassName = pkg.addWithSuffix(className).toRawString();
registerTypes.add(new TypeItem(fullClassName));
localData.scopeStack.add(new LocalRegAVM2Item(null, null, registerNames.size(), null));
localData.scopeStack.add(new LocalRegAVM2Item(null, null, registerNames.size(), null, new TypeItem(fullClassName)));
registerNames.add("this");
registerLines.add(0); //?
@@ -1704,7 +1704,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
registerLines.add(0); //?
localData.activationReg = registerNames.size() - 1;
registerTypes.add(new TypeItem("Object"));
localData.scopeStack.add(new LocalRegAVM2Item(null, null, localData.activationReg, null));
localData.scopeStack.add(new LocalRegAVM2Item(null, null, localData.activationReg, null, new TypeItem("Object")));
}
String mask = Configuration.registerNameFormat.get();

View File

@@ -150,7 +150,8 @@ public final class AbcIndexing {
hash = 17 * hash + Objects.hashCode(this.propName);
hash = 17 * hash + Objects.hashCode(this.parent);
hash = 17 * hash + this.propNsIndex;
hash = 17 * hash + System.identityHashCode(this.abc);
//?
//hash = 17 * hash + System.identityHashCode(this.abc);
return hash;
}
@@ -172,7 +173,8 @@ public final class AbcIndexing {
if (this.propNsIndex != other.propNsIndex) {
return false;
}
return (this.abc == other.abc);
return true; //?
//return (this.abc == other.abc);
}
}
@@ -254,15 +256,18 @@ public final class AbcIndexing {
public ABC abc;
public GraphTargetItem returnType;
public GraphTargetItem callReturnType;
public ValueKind value;
public GraphTargetItem objType;
public TraitIndex(Trait trait, ABC abc, GraphTargetItem type, ValueKind value, GraphTargetItem objType) {
public TraitIndex(Trait trait, ABC abc, GraphTargetItem type, GraphTargetItem callType, ValueKind value, GraphTargetItem objType) {
this.trait = trait;
this.abc = abc;
this.returnType = type;
this.callReturnType = callType;
this.value = value;
this.objType = objType;
}
@@ -299,7 +304,7 @@ public final class AbcIndexing {
private final Map<PropertyNsDef, TraitIndex> classNsProperties = new HashMap<>();
private final Map<PropertyNsDef, TraitIndex> scriptProperties = new HashMap<>();
public ClassIndex findClass(GraphTargetItem cls) {
if (!classes.containsKey(cls)) {
if (parent == null) {
@@ -309,6 +314,22 @@ public final class AbcIndexing {
}
return classes.get(cls);
}
public GraphTargetItem findPropertyType(ABC abc, GraphTargetItem cls, String propName, int ns, boolean findStatic, boolean findInstance) {
TraitIndex traitIndex = findProperty(new PropertyDef(propName, cls, abc, ns), findStatic, findInstance);
if (traitIndex == null) {
return TypeItem.UNBOUNDED;
}
return traitIndex.returnType;
}
public GraphTargetItem findPropertyCallType(ABC abc, GraphTargetItem cls, String propName, int ns, boolean findStatic, boolean findInstance) {
TraitIndex traitIndex = findProperty(new PropertyDef(propName, cls, abc, ns), findStatic, findInstance);
if (traitIndex == null) {
return TypeItem.UNBOUNDED;
}
return traitIndex.callReturnType;
}
public TraitIndex findScriptProperty(DottedChain ns) {
return findScriptProperty(ns.getLast(), ns.getWithoutLast());
@@ -354,8 +375,15 @@ public final class AbcIndexing {
return null;
}
public TraitIndex findProperty(PropertyDef prop, boolean findStatic, boolean findInstance) {
public TraitIndex findProperty(PropertyDef prop, boolean findStatic, boolean findInstance) {
/*System.out.println("searching " + prop);
for(PropertyDef p:instanceProperties.keySet()) {
if (p.parent.equals(new TypeItem("MyClass"))) {
System.out.println("- "+p);
}
}
System.out.println("-----------");*/
//search all static first
if (findStatic && classProperties.containsKey(prop)) {
if (!classProperties.containsKey(prop)) {
@@ -383,7 +411,7 @@ public final class AbcIndexing {
return instanceProperties.get(prop);
}
}
//now search parent class
AbcIndexing.ClassIndex ci = findClass(prop.parent);
if (ci != null && ci.parent != null && (prop.abc == null || prop.propNsIndex == 0)) {
@@ -395,9 +423,19 @@ public final class AbcIndexing {
return pti;
}
//parent public
return findProperty(new PropertyDef(prop.propName, new TypeItem(parentClass), null, 0), findStatic, findInstance);
pti = findProperty(new PropertyDef(prop.propName, new TypeItem(parentClass), null, 0), findStatic, findInstance);
if (pti != null) {
return pti;
}
}
if (parent != null) {
TraitIndex pti = parent.findProperty(prop, findStatic, findInstance);
if (pti != null) {
return pti;
}
}
return null;
}
@@ -418,6 +456,29 @@ public final class AbcIndexing {
}
}
private static GraphTargetItem getTraitCallReturnType(ABC abc, Trait t) {
if (t instanceof TraitSlotConst) {
return TypeItem.UNBOUNDED;
}
if (t instanceof TraitMethodGetterSetter) {
TraitMethodGetterSetter tmgs = (TraitMethodGetterSetter) t;
if (tmgs.kindType == Trait.TRAIT_GETTER) {
return TypeItem.UNBOUNDED;
}
if (tmgs.kindType == Trait.TRAIT_SETTER) {
return TypeItem.UNBOUNDED;
}
return PropertyAVM2Item.multinameToType(abc.method_info.get(tmgs.method_info).ret_type, abc.constants);
}
if (t instanceof TraitFunction) {
TraitFunction tf = (TraitFunction) t;
return PropertyAVM2Item.multinameToType(abc.method_info.get(tf.method_info).ret_type, abc.constants);
}
return TypeItem.UNBOUNDED;
}
private static GraphTargetItem getTraitReturnType(ABC abc, Trait t) {
if (t instanceof TraitSlotConst) {
TraitSlotConst tsc = (TraitSlotConst) t;
@@ -438,7 +499,9 @@ public final class AbcIndexing {
return TypeItem.UNBOUNDED;
}
}
}
return new TypeItem(DottedChain.FUNCTION);
}
if (t instanceof TraitFunction) {
return new TypeItem(DottedChain.FUNCTION);
}
@@ -454,12 +517,12 @@ public final class AbcIndexing {
}
if (map != null) {
PropertyDef dp = new PropertyDef(t.getName(abc).getName(abc.constants, new ArrayList<>() /*?*/, true, false), multinameToType(name_index, abc.constants), abc, abc.constants.getMultiname(t.name_index).namespace_index);
map.put(dp, new TraitIndex(t, abc, getTraitReturnType(abc, t), propValue, multinameToType(name_index, abc.constants)));
map.put(dp, new TraitIndex(t, abc, getTraitReturnType(abc, t), getTraitCallReturnType(abc, t), propValue, multinameToType(name_index, abc.constants)));
}
if (mapNs != null) {
Multiname m = abc.constants.getMultiname(t.name_index);
PropertyNsDef ndp = new PropertyNsDef(t.getName(abc).getName(abc.constants, new ArrayList<>() /*?*/, true, true/*FIXME ???*/), m == null || m.namespace_index == 0 ? DottedChain.EMPTY : m.getNamespace(abc.constants).getName(abc.constants), abc, m == null ? 0 : m.namespace_index);
TraitIndex ti = new TraitIndex(t, abc, getTraitReturnType(abc, t), propValue, multinameToType(name_index, abc.constants));
TraitIndex ti = new TraitIndex(t, abc, getTraitReturnType(abc, t), getTraitCallReturnType(abc, t), propValue, multinameToType(name_index, abc.constants));
if (!mapNs.containsKey(ndp)) {
mapNs.put(ndp, ti);
}

View File

@@ -1525,7 +1525,7 @@ public class ActionScript3Parser {
ParsedSymbol ss2 = lex();
if (ss2.type == SymbolType.PARENT_OPEN) {
List<GraphTargetItem> args = call(allOpenedNamespaces, thisType, pkg, needsActivation, importedClasses, openedNamespaces, registerVars, inFunction, inMethod, variables);
ret = new ConstructSuperAVM2Item(null, null, new LocalRegAVM2Item(null, null, 0, null), args);
ret = new ConstructSuperAVM2Item(null, null, new LocalRegAVM2Item(null, null, 0, null, new TypeItem("Object") /*?*/), args);
} else {//no costructor call, but it could be calling parent methods... => handle in expression
lexer.pushback(ss2);
lexer.pushback(s);