Fixed #1227 AS3 avoid recursion (stackoverflow) caused by newfunction instruction

This commit is contained in:
Jindra Petřík
2021-02-11 11:10:56 +01:00
parent df482b5343
commit 66b0d0bb13
23 changed files with 91 additions and 61 deletions

View File

@@ -3635,7 +3635,7 @@ public final class SWF implements SWFContainerItem, Timelined {
int mi = ((TraitMethodGetterSetter) t).method_info;
try {
documentPack.abc.findBody(mi).convert(new ConvertData(), "??", ScriptExportMode.AS, true, mi, documentPack.scriptIndex, cindex, documentPack.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true);
documentPack.abc.findBody(mi).convert(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) {
@@ -3711,7 +3711,7 @@ public final class SWF implements SWFContainerItem, Timelined {
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(new ConvertData(), "??", ScriptExportMode.AS, true, cinit, p.scriptIndex, cindex, p.abc, t, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true);
p.abc.findBody(cinit).convert(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

@@ -118,6 +118,8 @@ public class AVM2LocalData extends BaseLocalData {
public boolean inGetLoops = false;
public Set<Integer> seenMethods = new HashSet<>();
public AVM2LocalData() {
}
@@ -165,6 +167,7 @@ public class AVM2LocalData extends BaseLocalData {
finallyTargetParts = localData.finallyTargetParts;
pushDefaultPart = localData.pushDefaultPart;
finallyKinds = localData.finallyKinds;
seenMethods = localData.seenMethods;
}
public AVM2ConstantPool getConstants() {

View File

@@ -176,7 +176,7 @@ public class ScriptPack extends AS3ClassTreeItem {
}
ts.add(abc.script_info.get(scriptIndex).traits);
writer.mark();
abc.bodies.get(sinit_bodyIndex).convert(convertData, path +/*packageName +*/ "/.scriptinitializer", exportMode, true, sinit_index, scriptIndex, -1, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_SCRIPT_INITIALIZER, writer, new ArrayList<>(), ts, true);
abc.bodies.get(sinit_bodyIndex).convert(convertData, path +/*packageName +*/ "/.scriptinitializer", exportMode, true, sinit_index, scriptIndex, -1, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_SCRIPT_INITIALIZER, writer, new ArrayList<>(), ts, true, new HashSet<>());
scriptInitializerIsEmpty = !writer.getMark();
}
@@ -205,7 +205,7 @@ public class ScriptPack extends AS3ClassTreeItem {
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
if (!scriptInitializerIsEmpty) {
writer.startBlock();
abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/.scriptinitializer", exportMode, abc, null, writer, new ArrayList<>());
abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/.scriptinitializer", exportMode, abc, null, writer, new ArrayList<>(), new HashSet<>());
writer.endBlock();
} else {
writer.append(" ");

View File

@@ -802,10 +802,10 @@ public class AVM2Code implements Cloneable {
}
public void calculateDebugFileLine(ABC abc) {
calculateDebugFileLine(null, 0, 0, abc, new HashSet<>());
calculateDebugFileLine(null, 0, 0, abc, new HashSet<>(), new HashSet<>());
}
private boolean calculateDebugFileLine(String debugFile, int debugLine, int pos, ABC abc, Set<Integer> seen) {
private boolean calculateDebugFileLine(String debugFile, int debugLine, int pos, ABC abc, Set<Integer> seen, Set<Integer> seenMethods) {
while (pos < code.size()) {
AVM2Instruction ins = code.get(pos);
if (seen.contains(pos)) {
@@ -828,10 +828,15 @@ public class AVM2Code implements Cloneable {
//Only analyze NewFunction objects that are not immediately discarded by Pop.
//This avoids bogus functions used in obfuscation or special compilers that can lead to infinite recursion.
if ((pos + 1 < code.size()) && !(code.get(pos + 1).definition instanceof PopIns)) {
MethodBody innerBody = abc.findBody(ins.operands[0]);
if (innerBody != null) { //Ignore functions without body
innerBody.getCode().calculateDebugFileLine(debugFile, debugLine, 0, abc, new HashSet<>());
int newMethodInfo = ins.operands[0];
if (!seenMethods.contains(newMethodInfo)) { //avoid recursion
MethodBody innerBody = abc.findBody(newMethodInfo);
if (innerBody != null) { //Ignore functions without body
seenMethods.add(newMethodInfo);
innerBody.getCode().calculateDebugFileLine(debugFile, debugLine, 0, abc, new HashSet<>(), seenMethods);
}
}
}
}
@@ -851,7 +856,7 @@ public class AVM2Code implements Cloneable {
} else if (ins.definition instanceof IfTypeIns) {
try {
int newpos = adr2pos(ins.getTargetAddress());
calculateDebugFileLine(debugFile, debugLine, newpos, abc, seen);
calculateDebugFileLine(debugFile, debugLine, newpos, abc, seen, seenMethods);
} catch (ConvertException ex) {
return false;
}
@@ -863,7 +868,7 @@ public class AVM2Code implements Cloneable {
}
try {
int newpos = adr2pos(pos2adr(pos) + ins.operands[i]);
if (!calculateDebugFileLine(debugFile, debugLine, newpos, abc, seen)) {
if (!calculateDebugFileLine(debugFile, debugLine, newpos, abc, seen, seenMethods)) {
return false;
}
} catch (ConvertException ex) {
@@ -1990,7 +1995,6 @@ public class AVM2Code implements Cloneable {
}
}
}*/
if (value instanceof NewFunctionAVM2Item) {
NewFunctionAVM2Item f = (NewFunctionAVM2Item) value;
f.functionName = tsc.getName(abc).getName(abc.constants, fullyQualifiedNames, true, true);

View File

@@ -20,6 +20,7 @@ import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.model.LocalData;
import java.util.HashSet;
import java.util.List;
/**
@@ -51,7 +52,7 @@ public class CodeStats {
if (stats.stackpos > ms) {
ms = stats.stackpos;
}
writer.appendNoHilight(i + ":" + stats.stackpos + (deltastack >= 0 ? "+" + deltastack : deltastack) + "," + stats.scopepos + " " + stats.ins.toString(writer, LocalData.create(abc, null, fullyQualifiedNames))).newLine();
writer.appendNoHilight(i + ":" + stats.stackpos + (deltastack >= 0 ? "+" + deltastack : deltastack) + "," + stats.scopepos + " " + stats.ins.toString(writer, LocalData.create(abc, null, fullyQualifiedNames, new HashSet<>()))).newLine();
i++;
}
return writer;

View File

@@ -1643,8 +1643,8 @@ public class AVM2Graph extends Graph {
FullMultinameAVM2Item gptXmlMult = (FullMultinameAVM2Item) gpt.propertyName;
try {
isXMLList = fptXmlMult.isTopLevel("XMLList", aLocalData.abc, aLocalData.localRegNames, aLocalData.fullyQualifiedNames)
&& gptXmlMult.isTopLevel("XMLList", aLocalData.abc, aLocalData.localRegNames, aLocalData.fullyQualifiedNames);
isXMLList = fptXmlMult.isTopLevel("XMLList", aLocalData.abc, aLocalData.localRegNames, aLocalData.fullyQualifiedNames, aLocalData.seenMethods)
&& gptXmlMult.isTopLevel("XMLList", aLocalData.abc, aLocalData.localRegNames, aLocalData.fullyQualifiedNames, aLocalData.seenMethods);
} catch (InterruptedException ex) {
//ignore
}

View File

@@ -107,8 +107,8 @@ public class ConstructIns extends InstructionDefinition {
FullMultinameAVM2Item fptXmlMult = (FullMultinameAVM2Item) fpt.propertyName;
FullMultinameAVM2Item gptXmlMult = (FullMultinameAVM2Item) gpt.propertyName;
isXML = fptXmlMult.isXML(localData.abc, localData.localRegNames, localData.fullyQualifiedNames)
&& gptXmlMult.isXML(localData.abc, localData.localRegNames, localData.fullyQualifiedNames);
isXML = fptXmlMult.isXML(localData.abc, localData.localRegNames, localData.fullyQualifiedNames, localData.seenMethods)
&& gptXmlMult.isXML(localData.abc, localData.localRegNames, localData.fullyQualifiedNames, localData.seenMethods);
}
}
if (obj instanceof GetLexAVM2Item) {
@@ -135,8 +135,8 @@ public class ConstructIns extends InstructionDefinition {
FullMultinameAVM2Item fptRegExpMult = (FullMultinameAVM2Item) fpt.propertyName;
FullMultinameAVM2Item gptRegExpMult = (FullMultinameAVM2Item) gpt.propertyName;
isRegExp = fptRegExpMult.isTopLevel("RegExp", localData.abc, localData.localRegNames, localData.fullyQualifiedNames)
&& gptRegExpMult.isTopLevel("RegExp", localData.abc, localData.localRegNames, localData.fullyQualifiedNames);
isRegExp = fptRegExpMult.isTopLevel("RegExp", localData.abc, localData.localRegNames, localData.fullyQualifiedNames, localData.seenMethods)
&& gptRegExpMult.isTopLevel("RegExp", localData.abc, localData.localRegNames, localData.fullyQualifiedNames, localData.seenMethods);
}
}
if (obj instanceof GetLexAVM2Item) {

View File

@@ -74,7 +74,7 @@ public class ConstructPropIns extends InstructionDefinition {
multiname.property = false; //can be type
}
if (multiname.isXML(localData.abc, localData.localRegNames, localData.fullyQualifiedNames)) {
if (multiname.isXML(localData.abc, localData.localRegNames, localData.fullyQualifiedNames, localData.seenMethods)) {
if (args.size() == 1) {
GraphTargetItem arg = args.get(0);
List<GraphTargetItem> xmlLines = new ArrayList<>();
@@ -85,7 +85,7 @@ public class ConstructPropIns extends InstructionDefinition {
}
}//
boolean isRegExp = false;
if (multiname.isTopLevel("RegExp", localData.abc, localData.localRegNames, localData.fullyQualifiedNames)) {
if (multiname.isTopLevel("RegExp", localData.abc, localData.localRegNames, localData.fullyQualifiedNames, localData.seenMethods)) {
isRegExp = true;
}
if (isRegExp && (args.size() >= 1) && (args.get(0) instanceof StringAVM2Item) && (args.size() == 1 || (args.size() == 2 && args.get(1) instanceof StringAVM2Item))) {

View File

@@ -29,6 +29,7 @@ import com.jpexs.decompiler.graph.model.LocalData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
/**
*
@@ -87,16 +88,16 @@ public class FullMultinameAVM2Item extends AVM2Item {
return (name != null) || (namespace != null);
}
public boolean isTopLevel(String tname, ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public boolean isTopLevel(String tname, ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, Set<Integer> seenMethods) throws InterruptedException {
String cname;
if (name != null) {
cname = name.toString(LocalData.create(abc, localRegNames, fullyQualifiedNames));
cname = name.toString(LocalData.create(abc, localRegNames, fullyQualifiedNames, seenMethods));
} else {
cname = (abc.constants.getMultiname(multinameIndex).getName(abc.constants, fullyQualifiedNames, true, true));
}
String cns = "";
if (namespace != null) {
cns = namespace.toString(LocalData.create(abc, localRegNames, fullyQualifiedNames));
cns = namespace.toString(LocalData.create(abc, localRegNames, fullyQualifiedNames, seenMethods));
} else {
Namespace ns = abc.constants.getMultiname(multinameIndex).getNamespace(abc.constants);
if ((ns != null) && (ns.name_index != 0)) {
@@ -106,8 +107,8 @@ public class FullMultinameAVM2Item extends AVM2Item {
return cname.equals(tname) && cns.isEmpty();
}
public boolean isXML(ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
return isTopLevel("XML", abc, localRegNames, fullyQualifiedNames);
public boolean isXML(ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, Set<Integer> seenMethods) throws InterruptedException {
return isTopLevel("XML", abc, localRegNames, fullyQualifiedNames, seenMethods);
}
@Override

View File

@@ -29,6 +29,7 @@ import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.ScopeStack;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.LocalData;
import java.util.HashSet;
import java.util.List;
/**
@@ -70,6 +71,10 @@ public class NewFunctionAVM2Item extends AVM2Item {
@Override
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
if (localData.seenMethods.contains(methodIndex)) {
return writer.append("§§method(").append(methodIndex).append(")");
}
//if (methodIndex == 9141)
MethodBody body = abc.findBody(methodIndex);
writer.append("function");
writer.startMethod(methodIndex);
@@ -87,8 +92,8 @@ public class NewFunctionAVM2Item extends AVM2Item {
abc.method_info.get(methodIndex).getReturnTypeStr(writer, abc.constants, fullyQualifiedNames);
writer.startBlock();
if (body != null) {
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);
body.convert(new ConvertData(), path + "/inner", ScriptExportMode.AS, isStatic, methodIndex, scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), fullyQualifiedNames, null, false, new HashSet<>(localData.seenMethods));
body.toString(path + "/inner", ScriptExportMode.AS, abc, null, writer, fullyQualifiedNames, new HashSet<>(localData.seenMethods));
}
writer.endBlock();
writer.endMethod();

View File

@@ -12,7 +12,8 @@
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library.
* License along with this library.
*/
package com.jpexs.decompiler.flash.abc.avm2.parser.script;
import com.jpexs.helpers.Reference;
@@ -107,6 +108,7 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
@@ -1234,7 +1236,7 @@ public class AVM2SourceGenerator implements SourceGenerator {
initt.add(ci.abc.class_info.get(ci.index).static_traits);
try {
try {
pcinit.convert(d, "-", ScriptExportMode.AS, true, mi, -1, ci.index, ci.abc, null, new ScopeStack(), GraphTextWriter.TRAIT_CLASS_INITIALIZER, new NulWriter(), new ArrayList<>(), initt, false, new HashSet<>());
//FIXME! Add skinparts from _skinParts attribute of parent class!!!
} catch (InterruptedException ex) {
Logger.getLogger(AVM2SourceGenerator.class.getName()).log(Level.SEVERE, "Getting parent skinparts interrupted", ex);

View File

@@ -50,6 +50,7 @@ import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
@@ -285,7 +286,8 @@ public final class MethodBody implements Cloneable {
return ret;
}
public void convert(final ConvertData convertData, final String path, ScriptExportMode exportMode, final boolean isStatic, final int methodIndex, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ScopeStack scopeStack, final int initializerType, final NulWriter writer, final List<DottedChain> fullyQualifiedNames, final List<Traits> initTraits, boolean firstLevel) throws InterruptedException {
public void convert(final ConvertData convertData, final String path, ScriptExportMode exportMode, final boolean isStatic, final int methodIndex, final int scriptIndex, final int classIndex, final ABC abc, final Trait trait, final ScopeStack scopeStack, final int initializerType, final NulWriter writer, final List<DottedChain> fullyQualifiedNames, final List<Traits> initTraits, boolean firstLevel, Set<Integer> seenMethods) throws InterruptedException {
seenMethods.add(this.method_info);
if (debugMode) {
System.err.println("Decompiling " + path);
}
@@ -310,7 +312,7 @@ public final class MethodBody implements Cloneable {
convertedItems1 = converted.getCode().toGraphTargetItems(convertData.thisHasDefaultToPrimitive, convertData, path, methodIndex, isStatic, scriptIndex, classIndex, abc, converted, localRegNames, scopeStack, initializerType, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<>(), converted.getCode().visitCode(converted));
}
try (Statistics s = new Statistics("Graph.graphToString")) {
Graph.graphToString(convertedItems1, writer, LocalData.create(abc, localRegNames, fullyQualifiedNames));
Graph.graphToString(convertedItems1, writer, LocalData.create(abc, localRegNames, fullyQualifiedNames, seenMethods));
}
convertedItems = convertedItems1;
}
@@ -326,6 +328,7 @@ public final class MethodBody implements Cloneable {
throw ex;
} catch (Exception | OutOfMemoryError | StackOverflowError ex) {
convertException = ex;
ex.printStackTrace();
Throwable cause = ex.getCause();
if (ex instanceof ExecutionException && cause instanceof Exception) {
convertException = (Exception) cause;
@@ -340,7 +343,9 @@ public final class MethodBody implements Cloneable {
}
}
public GraphTextWriter toString(final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List<DottedChain> fullyQualifiedNames) throws InterruptedException {
public GraphTextWriter toString(final String path, ScriptExportMode exportMode, final ABC abc, final Trait trait, final GraphTextWriter writer, final List<DottedChain> fullyQualifiedNames, Set<Integer> seenMethods) throws InterruptedException {
seenMethods.add(method_info);
if (exportMode != ScriptExportMode.AS) {
getCode().toASMSource(abc, abc.constants, abc.method_info.get(this.method_info), this, exportMode, writer);
} else {
@@ -363,7 +368,7 @@ public final class MethodBody implements Cloneable {
writer.appendNoHilight(this.method_info);
writer.newLine();
}
Graph.graphToString(convertedItems, writer, LocalData.create(abc, localRegNames, fullyQualifiedNames));
Graph.graphToString(convertedItems, writer, LocalData.create(abc, localRegNames, fullyQualifiedNames, seenMethods));
//writer.endMethod();
} else if (convertException instanceof TimeoutException) {
// exception was logged in convert method
@@ -413,14 +418,14 @@ public final class MethodBody implements Cloneable {
return body;
}
public String toSource(int scriptIndex) {
public String toSource(int scriptIndex, Set<Integer> seenMethods) {
ConvertData convertData = new ConvertData();
convertData.deobfuscationMode = 0;
try {
convert(convertData, "", ScriptExportMode.AS, false, method_info, 0, 0, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true);
convert(convertData, "", ScriptExportMode.AS, false, method_info, 0, 0, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, seenMethods);
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false);
writer.indent().indent().indent();
toString("", ScriptExportMode.AS, abc, null, writer, new ArrayList<>());
toString("", ScriptExportMode.AS, abc, null, writer, new ArrayList<>(), seenMethods);
writer.unindent().unindent().unindent();
return writer.toString();
} catch (InterruptedException ex) {

View File

@@ -37,6 +37,7 @@ import com.jpexs.decompiler.graph.ScopeStack;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
@@ -136,7 +137,7 @@ public class TraitClass extends Trait implements TraitWithSlot {
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
if (!classInitializerIsEmpty) {
writer.startBlock();
abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, abc, this, writer, fullyQualifiedNames);
abc.bodies.get(bodyIndex).toString(path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>());
writer.endBlock();
} else {
//Note: There must be trait/method highlight even if the initializer is empty to TraitList in GUI to work correctly
@@ -184,7 +185,7 @@ public class TraitClass extends Trait implements TraitWithSlot {
writer.appendNoHilight(")").startBlock();
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
if (body != null) {
body.toString(path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, abc, this, writer, fullyQualifiedNames);
body.toString(path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>());
}
}
@@ -224,7 +225,7 @@ public class TraitClass extends Trait implements TraitWithSlot {
writer.mark();
List<Traits> ts = new ArrayList<>();
ts.add(classInfo.static_traits);
abc.bodies.get(bodyIndex).convert(convertData, path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, true, classInfo.cinit_index, scriptIndex, class_info, abc, this, new ScopeStack(), GraphTextWriter.TRAIT_CLASS_INITIALIZER, writer, fullyQualifiedNames, ts, true);
abc.bodies.get(bodyIndex).convert(convertData, path +/*packageName +*/ "/" + instanceInfoName + ".staticinitializer", exportMode, true, classInfo.cinit_index, scriptIndex, class_info, abc, this, new ScopeStack(), GraphTextWriter.TRAIT_CLASS_INITIALIZER, writer, fullyQualifiedNames, ts, true, new HashSet<>());
classInitializerIsEmpty = !writer.getMark();
}
@@ -234,7 +235,7 @@ public class TraitClass extends Trait implements TraitWithSlot {
if (bodyIndex != -1) {
List<Traits> ts = new ArrayList<>();
ts.add(instanceInfo.instance_traits);
abc.bodies.get(bodyIndex).convert(convertData, path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, false, instanceInfo.iinit_index, scriptIndex, class_info, abc, this, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, writer, fullyQualifiedNames, ts, true);
abc.bodies.get(bodyIndex).convert(convertData, path +/*packageName +*/ "/" + instanceInfoName + ".initializer", exportMode, false, instanceInfo.iinit_index, scriptIndex, class_info, abc, this, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, writer, fullyQualifiedNames, ts, true, new HashSet<>());
}
}

View File

@@ -30,6 +30,7 @@ import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.ScopeStack;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
@@ -88,7 +89,7 @@ public class TraitFunction extends Trait implements TraitWithSlot {
writer.startBlock();
int bodyIndex = abc.findBodyIndex(method_info);
if (bodyIndex != -1) {
abc.bodies.get(bodyIndex).toString(path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, abc, this, writer, fullyQualifiedNames);
abc.bodies.get(bodyIndex).toString(path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>());
}
writer.endBlock();
@@ -105,7 +106,7 @@ public class TraitFunction extends Trait implements TraitWithSlot {
convertHeader(parent, convertData, path, abc, isStatic, exportMode, scriptIndex, classIndex, writer, fullyQualifiedNames, parallel);
int bodyIndex = abc.findBodyIndex(method_info);
if (bodyIndex != -1) {
abc.bodies.get(bodyIndex).convert(convertData, path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true);
abc.bodies.get(bodyIndex).convert(convertData, path + "." + abc.constants.getMultiname(name_index).getName(abc.constants, fullyQualifiedNames, false, true), exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true, new HashSet<>());
}
writer.endMethod();
}

View File

@@ -33,6 +33,7 @@ import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.ScopeStack;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
/**
@@ -116,7 +117,7 @@ public class TraitMethodGetterSetter extends Trait {
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
if (!(classIndex != -1 && abc.instance_info.get(classIndex).isInterface() || bodyIndex == -1)) {
if (bodyIndex != -1) {
abc.bodies.get(bodyIndex).convert(convertData, path, exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true);
abc.bodies.get(bodyIndex).convert(convertData, path, exportMode, isStatic, method_info, scriptIndex, classIndex, abc, this, new ScopeStack(), 0, writer, fullyQualifiedNames, null, true, new HashSet<>());
}
}
}
@@ -143,7 +144,7 @@ public class TraitMethodGetterSetter extends Trait {
convertTraitHeader(abc, writer);
}
if (bodyIndex != -1) {
abc.bodies.get(bodyIndex).toString(path, exportMode, abc, this, writer, fullyQualifiedNames);
abc.bodies.get(bodyIndex).toString(path, exportMode, abc, this, writer, fullyQualifiedNames, new HashSet<>());
}
} else {
String retTypeRaw = abc.method_info.get(method_info).getReturnTypeRaw(abc.constants, fullyQualifiedNames);

View File

@@ -39,6 +39,7 @@ import com.jpexs.decompiler.graph.model.LocalData;
import com.jpexs.helpers.Helper;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
/**
@@ -121,7 +122,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
writer.newLine();
}
if (exportMode != ScriptExportMode.AS_METHOD_STUBS) {
assignment.value.toString(writer, LocalData.create(abc, new HashMap<>(), fullyQualifiedNames));
assignment.value.toString(writer, LocalData.create(abc, new HashMap<>(), fullyQualifiedNames, new HashSet<>()));
}
writer.endMethod();
writer.endTrait();
@@ -161,7 +162,7 @@ public class TraitSlotConst extends Trait implements TraitWithSlot {
if (convertData.assignedValues.containsKey(this)) {
GraphTargetItem val = convertData.assignedValues.get(this).value;
if (val instanceof NewFunctionAVM2Item) {
return val.toString(writer, LocalData.create(abc, new HashMap<>(), fullyQualifiedNames));
return val.toString(writer, LocalData.create(abc, new HashMap<>(), fullyQualifiedNames, new HashSet<>()));
}
}
getNameStr(writer, abc, fullyQualifiedNames);

View File

@@ -106,7 +106,7 @@ public class AS3ScriptExporter {
StringBuilder out = new StringBuilder();
int method = t.method_info;
try {
pack.abc.findBody(method).convert(new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true);
pack.abc.findBody(method).convert(new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>());
List<GraphTargetItem> ci = pack.abc.findBody(method).convertedItems;
if (!ci.isEmpty()) {
@@ -179,7 +179,7 @@ public class AS3ScriptExporter {
StringBuilder out = new StringBuilder();
int method = t.method_info;
try {
pack.abc.findBody(method).convert(new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true);
pack.abc.findBody(method).convert(new ConvertData(), "??", ScriptExportMode.AS, false, method, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>()/*??*/);
List<GraphTargetItem> ci = pack.abc.findBody(method).convertedItems;
if (!ci.isEmpty() && (ci.get(0) instanceof DeclarationAVM2Item)) {
@@ -270,7 +270,7 @@ public class AS3ScriptExporter {
int iinit = pack.abc.instance_info.get(cindex).iinit_index;
try {
pack.abc.findBody(iinit).convert(new ConvertData(), "??", ScriptExportMode.AS, false, iinit, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true);
pack.abc.findBody(iinit).convert(new ConvertData(), "??", ScriptExportMode.AS, false, iinit, pack.scriptIndex, cindex, pack.abc, t, new ScopeStack(), 0/*?*/, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>());
List<GraphTargetItem> iinitBody = pack.abc.findBody(iinit).convertedItems;
for (GraphTargetItem it : iinitBody) {
if (it instanceof InitPropertyAVM2Item) {

View File

@@ -2455,7 +2455,7 @@ public class XFLConverter {
MethodBody constructorBody = abc.findBody(constructorMethodIndex);
try {
if (constructorBody.convertedItems == null) {
constructorBody.convert(new ConvertData(), "??", ScriptExportMode.AS, true, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true);
constructorBody.convert(new ConvertData(), "??", ScriptExportMode.AS, true, constructorMethodIndex, pack.scriptIndex, classIndex, abc, null, new ScopeStack(), GraphTextWriter.TRAIT_INSTANCE_INITIALIZER, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>());
}
Map<Integer, Integer> frameToTraitMultiname = new HashMap<>();
@@ -2518,9 +2518,9 @@ public class XFLConverter {
MethodBody frameBody = abc.findBody(methodIndex);
StringBuilder scriptBuilder = new StringBuilder();
frameBody.convert(new ConvertData(), "??", ScriptExportMode.AS, false, methodIndex, pack.scriptIndex, classIndex, abc, methodTrait, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true);
frameBody.convert(new ConvertData(), "??", ScriptExportMode.AS, false, methodIndex, pack.scriptIndex, classIndex, abc, methodTrait, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), new ArrayList<>(), true, new HashSet<>());
StringBuilderTextWriter writer = new StringBuilderTextWriter(Configuration.getCodeFormatting(), scriptBuilder);
frameBody.toString("??", ScriptExportMode.AS, abc, methodTrait, writer, new ArrayList<>());
frameBody.toString("??", ScriptExportMode.AS, abc, methodTrait, writer, new ArrayList<>(), new HashSet<>());
String script = scriptBuilder.toString();
ret.put(frame, script);

View File

@@ -1759,9 +1759,6 @@ public class Graph {
boolean vCanHandleVisited = canHandleVisited(localData, part);
/*if (part.start == 25) {
new RuntimeException().printStackTrace();
}*/
if (vCanHandleVisited) {
if (visited.contains(part)) {
String labelName = "addr" + part.start;

View File

@@ -21,7 +21,9 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
import com.jpexs.decompiler.flash.action.model.ConstantPool;
import com.jpexs.decompiler.graph.DottedChain;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
*
@@ -39,6 +41,8 @@ public class LocalData {
public List<DottedChain> fullyQualifiedNames;
public Set<Integer> seenMethods = new HashSet<>();
public ABC abc;
public static LocalData create(ConstantPool constants) {
@@ -47,12 +51,13 @@ public class LocalData {
return localData;
}
public static LocalData create(ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames) {
public static LocalData create(ABC abc, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames, Set<Integer> seenMethods) {
LocalData localData = new LocalData();
localData.abc = abc;
localData.constantsAvm2 = abc.constants;
localData.localRegNames = localRegNames;
localData.fullyQualifiedNames = fullyQualifiedNames;
localData.seenMethods = seenMethods;
return localData;
}
}