mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-09-25 09:50:51 +00:00
decompilation timeouts
This commit is contained in:
@@ -53,7 +53,15 @@ public class Configuration {
|
||||
* Limit of code subs (for obfuscated code)
|
||||
*/
|
||||
public static final int SUBLIMITER = 500;
|
||||
//using parameter names in decompiling may cause problems because oficial programs like Flash CS 5.5 inserts wrong parameter names indices
|
||||
/**
|
||||
* Decompilation timeout in seconds
|
||||
*/
|
||||
public static final int DECOMPILATION_TIMEOUT = 30 * 60;
|
||||
/**
|
||||
* Decompilation timeout for a single method in AS3 or single action in AS1/2 in seconds
|
||||
*/
|
||||
public static final int DECOMPILATION_TIMEOUT_SINGLE_METHOD = 5;
|
||||
//using parameter names in decompiling may cause problems because official programs like Flash CS 5.5 inserts wrong parameter names indices
|
||||
public static final boolean PARAM_NAMES_ENABLE = false;
|
||||
private static HashMap<String, Object> config = new HashMap<>();
|
||||
/**
|
||||
|
||||
@@ -622,9 +622,9 @@ public class SWF {
|
||||
|
||||
try {
|
||||
executor.shutdown();
|
||||
executor.awaitTermination(30, TimeUnit.MINUTES);
|
||||
executor.awaitTermination(Configuration.DECOMPILATION_TIMEOUT, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException ex) {
|
||||
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, "30 minutes ActionScript export limit reached", ex);
|
||||
Logger.getLogger(ABC.class.getName()).log(Level.SEVERE, Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT) + " ActionScript export limit reached", ex);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.CodeStats;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.ConstantPool;
|
||||
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
|
||||
import com.jpexs.decompiler.flash.action.Action;
|
||||
import com.jpexs.decompiler.flash.helpers.Helper;
|
||||
import com.jpexs.decompiler.flash.helpers.Highlighting;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
@@ -31,6 +32,10 @@ import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -103,7 +108,7 @@ public class MethodBody implements Cloneable, Serializable {
|
||||
return ret;
|
||||
}
|
||||
|
||||
public String toString(String path, boolean pcode, boolean isStatic, int scriptIndex, int classIndex, ABC abc, ConstantPool constants, MethodInfo method_info[], Stack<GraphTargetItem> scopeStack, boolean isStaticInitializer, boolean hilight, List<String> fullyQualifiedNames, Traits initTraits) {
|
||||
public String toString(final String path, boolean pcode, final boolean isStatic, final int scriptIndex, final int classIndex, final ABC abc, final ConstantPool constants, final MethodInfo method_info[], final Stack<GraphTargetItem> scopeStack, final boolean isStaticInitializer, final boolean hilight, final List<String> fullyQualifiedNames, final Traits initTraits) {
|
||||
if (debugMode) {
|
||||
System.err.println("Decompiling " + path);
|
||||
}
|
||||
@@ -118,30 +123,46 @@ public class MethodBody implements Cloneable, Serializable {
|
||||
if (pcode) {
|
||||
s += code.toASMSource(constants, this, false);
|
||||
} else {
|
||||
AVM2Code deobfuscated = null;
|
||||
MethodBody b = (MethodBody) Helper.deepCopy(this);
|
||||
deobfuscated = b.code;
|
||||
deobfuscated.markMappedOffsets();
|
||||
if ((Boolean) Configuration.getConfig("autoDeobfuscate", true)) {
|
||||
try {
|
||||
deobfuscated.removeTraps(constants, b, abc, scriptIndex, classIndex, isStatic, path);
|
||||
} catch (Exception | StackOverflowError ex) {
|
||||
Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Error during remove traps in " + path, ex);
|
||||
}
|
||||
}
|
||||
//deobfuscated.restoreControlFlow(constants, b);
|
||||
//try {
|
||||
s += deobfuscated.toSource(path, isStatic, scriptIndex, classIndex, abc, constants, method_info, b, hilight, getLocalRegNames(abc), scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<Integer, Integer>(), deobfuscated.visitCode(b));
|
||||
s = s.trim();
|
||||
if (s.equals("")) {
|
||||
s = " ";
|
||||
}
|
||||
if (hilight) {
|
||||
s = Highlighting.hilighMethod(s, this.method_info);
|
||||
try {
|
||||
s += Helper.timedCall(new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
return toSource(path, isStatic, scriptIndex, classIndex, abc, constants, method_info, scopeStack, isStaticInitializer, hilight, fullyQualifiedNames, initTraits);
|
||||
}
|
||||
}, Configuration.DECOMPILATION_TIMEOUT_SINGLE_METHOD, TimeUnit.SECONDS);
|
||||
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
|
||||
Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error", ex);
|
||||
s += "/*\r\n * Decompilation error\r\n * Timeout (" + Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT_SINGLE_METHOD) + ") was reached\r\n */";
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public String toSource(String path, boolean isStatic, int scriptIndex, int classIndex, ABC abc, ConstantPool constants, MethodInfo method_info[], Stack<GraphTargetItem> scopeStack, boolean isStaticInitializer, boolean hilight, List<String> fullyQualifiedNames, Traits initTraits) {
|
||||
AVM2Code deobfuscated = null;
|
||||
MethodBody b = (MethodBody) Helper.deepCopy(this);
|
||||
deobfuscated = b.code;
|
||||
deobfuscated.markMappedOffsets();
|
||||
if ((Boolean) Configuration.getConfig("autoDeobfuscate", true)) {
|
||||
try {
|
||||
deobfuscated.removeTraps(constants, b, abc, scriptIndex, classIndex, isStatic, path);
|
||||
} catch (Exception | StackOverflowError ex) {
|
||||
Logger.getLogger(MethodBody.class.getName()).log(Level.SEVERE, "Error during remove traps in " + path, ex);
|
||||
}
|
||||
}
|
||||
//deobfuscated.restoreControlFlow(constants, b);
|
||||
//try {
|
||||
String s = deobfuscated.toSource(path, isStatic, scriptIndex, classIndex, abc, constants, method_info, b, hilight, getLocalRegNames(abc), scopeStack, isStaticInitializer, fullyQualifiedNames, initTraits, Graph.SOP_USE_STATIC, new HashMap<Integer, Integer>(), deobfuscated.visitCode(b));
|
||||
s = s.trim();
|
||||
if (s.equals("")) {
|
||||
s = " ";
|
||||
}
|
||||
if (hilight) {
|
||||
s = Highlighting.hilighMethod(s, this.method_info);
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.Configuration;
|
||||
import com.jpexs.decompiler.flash.DisassemblyListener;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
import com.jpexs.decompiler.flash.SWFInputStream;
|
||||
@@ -49,6 +50,7 @@ import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.helpers.Helper;
|
||||
import com.jpexs.decompiler.flash.helpers.Highlighting;
|
||||
import com.jpexs.decompiler.flash.helpers.collections.MyEntry;
|
||||
import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.graph.Graph;
|
||||
import com.jpexs.decompiler.graph.GraphSource;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
@@ -62,6 +64,9 @@ import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -408,7 +413,7 @@ public class Action implements GraphSourceItem {
|
||||
* @param path
|
||||
* @return ASM source as String
|
||||
*/
|
||||
public static String actionsToString(List<DisassemblyListener> listeners, long address, List<Action> list, List<Long> importantOffsets, List<String> constantPool, int version, boolean hex, long swfPos, String path) {
|
||||
private static String actionsToString(List<DisassemblyListener> listeners, long address, List<Action> list, List<Long> importantOffsets, List<String> constantPool, int version, boolean hex, long swfPos, String path) {
|
||||
long offset;
|
||||
if (importantOffsets == null) {
|
||||
//setActionsAddresses(list, 0, version);
|
||||
@@ -434,6 +439,10 @@ public class Action implements GraphSourceItem {
|
||||
}
|
||||
pos++;
|
||||
if (hex) {
|
||||
if (lastPush) {
|
||||
ret.append("\r\n");
|
||||
lastPush = false;
|
||||
}
|
||||
ret.append("<ffdec:hex>");/* +"0x"+Helper.formatAddress(a.getFileAddress())+": "+*/;
|
||||
ret.append(Helper.bytesToHexString(a.getBytes(version)));
|
||||
ret.append("</ffdec:hex>\r\n");
|
||||
@@ -707,15 +716,22 @@ public class Action implements GraphSourceItem {
|
||||
* @param path
|
||||
* @return String with Source code
|
||||
*/
|
||||
public static String actionsToSource(List<Action> actions, int version, String path) {
|
||||
public static String actionsToSource(final List<Action> actions, final int version, final String path) {
|
||||
try {
|
||||
//List<ActionItem> tree = actionsToTree(new HashMap<Integer, String>(), actions, version);
|
||||
int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC;
|
||||
return Helper.timedCall(new Callable<String>() {
|
||||
@Override
|
||||
public String call() throws Exception {
|
||||
//List<ActionItem> tree = actionsToTree(new HashMap<Integer, String>(), actions, version);
|
||||
int staticOperation = Graph.SOP_USE_STATIC; //(Boolean) Configuration.getConfig("autoDeobfuscate", true) ? Graph.SOP_SKIP_STATIC : Graph.SOP_USE_STATIC;
|
||||
|
||||
List<GraphTargetItem> tree = actionsToTree(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>(), actions, version, staticOperation, path);
|
||||
List<GraphTargetItem> tree = actionsToTree(new HashMap<Integer, String>(), new HashMap<String, GraphTargetItem>(), new HashMap<String, GraphTargetItem>(), actions, version, staticOperation, path);
|
||||
|
||||
|
||||
return Graph.graphToString(tree);
|
||||
return Graph.graphToString(tree);
|
||||
}
|
||||
}, Configuration.DECOMPILATION_TIMEOUT_SINGLE_METHOD, TimeUnit.SECONDS);
|
||||
} catch (TimeoutException ex) {
|
||||
Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error", ex);
|
||||
return "/*\r\n * Decompilation error\r\n * Timeout (" + Helper.formatTimeToText(Configuration.DECOMPILATION_TIMEOUT_SINGLE_METHOD) + ") was reached\r\n */";
|
||||
} catch (Exception | OutOfMemoryError | StackOverflowError ex2) {
|
||||
Logger.getLogger(Action.class.getName()).log(Level.SEVERE, "Decompilation error", ex2);
|
||||
if (ex2 instanceof OutOfMemoryError) {
|
||||
|
||||
@@ -1404,6 +1404,12 @@ public class MainFrame extends AppRibbonFrame implements ActionListener, TreeSel
|
||||
@Override
|
||||
public void run() {
|
||||
if (record.getLevel() == Level.SEVERE) {
|
||||
if (errorNotificationButton == null) {
|
||||
// todo: honfika
|
||||
// why null?
|
||||
return;
|
||||
}
|
||||
|
||||
errorNotificationButton.setIcon(View.getIcon("error16"));
|
||||
errorNotificationButton.setToolTipText(translate("errors.present"));
|
||||
if (timer != null) {
|
||||
|
||||
@@ -168,7 +168,7 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
private void cacheScript(ASMSource src) {
|
||||
if (!cache.contains(src)) {
|
||||
List<Action> as = src.getActions(SWF.DEFAULT_VERSION);
|
||||
String s = com.jpexs.decompiler.flash.action.Action.actionsToSource(as, SWF.DEFAULT_VERSION, src.toString()/*FIXME?*/);
|
||||
String s = Action.actionsToSource(as, SWF.DEFAULT_VERSION, src.toString()/*FIXME?*/);
|
||||
List<Highlighting> hilights = Highlighting.getInstrHighlights(s);
|
||||
String srcNoHex = Highlighting.stripHilights(s);
|
||||
cache.put(src, new CachedScript(srcNoHex, hilights));
|
||||
@@ -567,6 +567,10 @@ public class ActionPanel extends JPanel implements ActionListener {
|
||||
}
|
||||
|
||||
public void setDecompiledEditMode(boolean val) {
|
||||
if (lastASM == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
String pref = lastASM.getActionSourcePrefix();
|
||||
int lastPos = decompiledEditor.getCaretPosition();
|
||||
int lastLine = decompiledEditor.getLine();
|
||||
|
||||
@@ -34,6 +34,13 @@ import java.util.BitSet;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Stack;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -46,6 +53,8 @@ import java.util.regex.Pattern;
|
||||
*/
|
||||
public class Helper {
|
||||
|
||||
private static final ExecutorService THREAD_POOL = Executors.newCachedThreadPool();
|
||||
|
||||
/**
|
||||
* Converts array of int values to string
|
||||
*
|
||||
@@ -504,4 +513,37 @@ public class Helper {
|
||||
timeStr += Helper.padZeros(timeS, 2) + "." + Helper.padZeros(timeMs, 3);
|
||||
return timeStr;
|
||||
}
|
||||
|
||||
public static String formatTimeToText(int timeS) {
|
||||
long timeM = timeS / 60;
|
||||
timeS = timeS % 60;
|
||||
long timeH = timeM / 60;
|
||||
timeM = timeM % 60;
|
||||
|
||||
String timeStr = "";
|
||||
if (timeH > 0) {
|
||||
timeStr += timeH + (timeH > 1 ? " hours" : " hour");
|
||||
}
|
||||
if (timeM > 0) {
|
||||
if (timeStr.length() > 0) {
|
||||
timeStr += " and ";
|
||||
}
|
||||
timeStr += timeM + (timeM > 1 ? " minutes" : " minute");
|
||||
}
|
||||
if (timeS > 0) {
|
||||
if (timeStr.length() > 0) {
|
||||
timeStr += " and ";
|
||||
}
|
||||
timeStr += timeS + (timeS > 1 ? " seconds" : " second");
|
||||
}
|
||||
|
||||
// (currently) used only in log, so no localization is required
|
||||
return timeStr;
|
||||
}
|
||||
|
||||
public static <T> T timedCall(Callable<T> c, long timeout, TimeUnit timeUnit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||
FutureTask<T> task = new FutureTask<T>(c);
|
||||
THREAD_POOL.execute(task);
|
||||
return task.get(timeout, timeUnit);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user