mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-14 19:11:52 +00:00
Fixed #1227 AS3 avoid recursion (stackoverflow) caused by newfunction instruction
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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(" ");
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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))) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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<>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user