mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-06-14 15:41:54 +00:00
Added: #2477 Option to disable AS2 detection of uninitialized class fields
Added: AS2 detection of uninitialized class fields is cancellable and shows progress Changed: Icon of "Deobfuscation options" menu from pile of pills to medkit Fixed: Comments color highlighting
This commit is contained in:
@@ -243,6 +243,9 @@ public class DecompilerPool {
|
||||
future.cancel(true);
|
||||
throw ex;
|
||||
} catch (ExecutionException ex) {
|
||||
if (ex.getCause() instanceof InterruptedException) {
|
||||
throw (InterruptedException) ex.getCause();
|
||||
}
|
||||
Logger.getLogger(DecompilerPool.class.getName()).log(Level.SEVERE, null, ex);
|
||||
} finally {
|
||||
List<Future<HighlightedText>> futures = openableToFutures.get(swf);
|
||||
|
||||
@@ -576,6 +576,15 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
|
||||
* Uninitialized AS2 class traits. Class name to trait name to trait.
|
||||
*/
|
||||
private volatile Map<String, Map<String, com.jpexs.decompiler.flash.action.as2.Trait>> uninitializedAs2ClassTraits = null;
|
||||
|
||||
/**
|
||||
* Detecting uninitilized class fields
|
||||
*/
|
||||
@Internal
|
||||
private boolean detectingUninitializedClassFields = false;
|
||||
|
||||
@Internal
|
||||
private UninitializedClassFieldsDetector uninitializedClassFieldsDetector = new UninitializedClassFieldsDetector();
|
||||
|
||||
/**
|
||||
* ExporterInfo tag.
|
||||
@@ -664,6 +673,10 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
|
||||
*/
|
||||
private final Object charactersLock = new Object();
|
||||
|
||||
public UninitializedClassFieldsDetector getUninitializedClassFieldsDetector() {
|
||||
return uninitializedClassFieldsDetector;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets main GFX exporterinfo tag
|
||||
*
|
||||
@@ -6208,24 +6221,40 @@ public final class SWF implements SWFContainerItem, Timelined, Openable {
|
||||
* @throws java.lang.InterruptedException On interruption
|
||||
*/
|
||||
public void calculateAs2UninitializedClassTraits() throws InterruptedException {
|
||||
setDetectingUninitialized(true);
|
||||
uninitializedAs2ClassTraits = new HashMap<>();
|
||||
UninitializedClassFieldsDetector detector = new UninitializedClassFieldsDetector();
|
||||
try {
|
||||
uninitializedAs2ClassTraits = detector.calculateAs2UninitializedClassTraits(this);
|
||||
} catch (Throwable t) {
|
||||
uninitializedAs2ClassTraits = getUninitializedClassFieldsDetector().calculateAs2UninitializedClassTraits(this);
|
||||
} catch (Throwable t) {
|
||||
uninitializedAs2ClassTraits = null;
|
||||
throw t;
|
||||
} finally {
|
||||
setDetectingUninitialized(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private synchronized void setDetectingUninitialized(boolean val) {
|
||||
this.detectingUninitializedClassFields = val;
|
||||
}
|
||||
|
||||
private synchronized boolean isDetectingUninitialized() {
|
||||
return detectingUninitializedClassFields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets uninitialized class traits in AS2.
|
||||
*
|
||||
* @return Map of class name to map of trait name to trait
|
||||
*/
|
||||
public synchronized Map<String, Map<String, com.jpexs.decompiler.flash.action.as2.Trait>> getUninitializedAs2ClassTraits() throws InterruptedException {
|
||||
public Map<String, Map<String, com.jpexs.decompiler.flash.action.as2.Trait>> getUninitializedAs2ClassTraits() throws InterruptedException {
|
||||
if (Configuration.skipDetectionOfUnitializedClassFields.get()) {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
if (CancellableWorker.isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
if (isDetectingUninitialized()) {
|
||||
return new LinkedHashMap<>();
|
||||
}
|
||||
if (uninitializedAs2ClassTraits == null) {
|
||||
calculateAs2UninitializedClassTraits();
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.action;
|
||||
|
||||
import com.jpexs.decompiler.flash.AppResources;
|
||||
import com.jpexs.decompiler.flash.BaseLocalData;
|
||||
import com.jpexs.decompiler.flash.FinalProcessLocalData;
|
||||
import com.jpexs.decompiler.flash.SWF;
|
||||
@@ -48,6 +49,7 @@ import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction;
|
||||
import com.jpexs.decompiler.flash.action.swf5.ActionEquals2;
|
||||
import com.jpexs.decompiler.flash.action.swf6.ActionStrictEquals;
|
||||
import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2;
|
||||
import com.jpexs.decompiler.flash.configuration.Configuration;
|
||||
import com.jpexs.decompiler.flash.ecma.Null;
|
||||
import com.jpexs.decompiler.flash.ecma.Undefined;
|
||||
import com.jpexs.decompiler.graph.AbstractGraphTargetVisitor;
|
||||
@@ -67,6 +69,7 @@ import com.jpexs.decompiler.graph.ThrowState;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.decompiler.graph.model.BinaryOpItem;
|
||||
import com.jpexs.decompiler.graph.model.BreakItem;
|
||||
import com.jpexs.decompiler.graph.model.CommentItem;
|
||||
import com.jpexs.decompiler.graph.model.GotoItem;
|
||||
import com.jpexs.decompiler.graph.model.IfItem;
|
||||
import com.jpexs.decompiler.graph.model.PopItem;
|
||||
@@ -129,7 +132,7 @@ public class ActionGraph extends Graph {
|
||||
this.insideDoInitAction = insideDoInitAction;
|
||||
this.insideFunction = insideFunction;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get uninitialized class traits
|
||||
*
|
||||
@@ -616,6 +619,9 @@ public class ActionGraph extends Graph {
|
||||
if (insideDoInitAction && !insideFunction) {
|
||||
ActionScript2ClassDetector detector = new ActionScript2ClassDetector();
|
||||
detector.checkClass(uninitializedClassTraits, ret, ((ActionGraphSource) code).getVariables(), path);
|
||||
if (Configuration.skipDetectionOfUnitializedClassFields.get()) {
|
||||
ret.add(0, new CommentItem(AppResources.translate("decompilationWarning.as2.noUninitializedClassFieldsDetection")));
|
||||
}
|
||||
}
|
||||
ActionLocalData ald = (ActionLocalData) localData;
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import com.jpexs.decompiler.flash.tags.base.ASMSource;
|
||||
import com.jpexs.decompiler.graph.AbstractGraphTargetVisitor;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.helpers.CancellableWorker;
|
||||
import com.jpexs.helpers.ProgressListener;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
@@ -48,6 +49,22 @@ import java.util.Map;
|
||||
*/
|
||||
public class UninitializedClassFieldsDetector {
|
||||
|
||||
private List<ProgressListener> progressListeners = new ArrayList<>();
|
||||
|
||||
public void addProgressListener(ProgressListener listener) {
|
||||
progressListeners.add(listener);
|
||||
}
|
||||
|
||||
public void removeProgressListener(ProgressListener listener) {
|
||||
progressListeners.remove(listener);
|
||||
}
|
||||
|
||||
private void fireProgress(String status) {
|
||||
for (ProgressListener listener : progressListeners) {
|
||||
listener.status(status);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets path of variable and its getMembers: a.b.c.d => [a,b,c,d].
|
||||
*
|
||||
@@ -210,6 +227,7 @@ public class UninitializedClassFieldsDetector {
|
||||
DoInitActionTag doi = (DoInitActionTag) asm;
|
||||
String exportName = doi.getSwf().getCharacter(doi.getCharacterId()).getExportName();
|
||||
if (exportName != null && exportName.startsWith("__Packages.")) {
|
||||
fireProgress(key);
|
||||
List<GraphTargetItem> tree = asm.getActionsToTree();
|
||||
for (GraphTargetItem item : tree) {
|
||||
if (item instanceof InterfaceActionItem) {
|
||||
@@ -265,7 +283,7 @@ public class UninitializedClassFieldsDetector {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
classesAsms.add(doi);
|
||||
}
|
||||
}
|
||||
@@ -295,6 +313,7 @@ public class UninitializedClassFieldsDetector {
|
||||
DoInitActionTag doi = (DoInitActionTag) asm;
|
||||
String exportName = doi.getSwf().getCharacter(doi.getCharacterId()).getExportName();
|
||||
if (exportName != null && exportName.startsWith("__Packages.")) {
|
||||
fireProgress(key);
|
||||
List<GraphTargetItem> tree = asm.getActionsToTree();
|
||||
for (GraphTargetItem item : tree) {
|
||||
if (item instanceof ClassActionItem) {
|
||||
@@ -347,6 +366,7 @@ public class UninitializedClassFieldsDetector {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
ASMSource asm = asms.get(key);
|
||||
fireProgress(key);
|
||||
List<GraphTargetItem> tree = asm.getActionsToTree();
|
||||
for (GraphTargetItem item : tree) {
|
||||
AbstractGraphTargetVisitor visitor = new AbstractGraphTargetVisitor() {
|
||||
@@ -383,6 +403,22 @@ public class UninitializedClassFieldsDetector {
|
||||
item.visitRecursively(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Removed cached version of classes - allow reparsing using detected uninitialized fields
|
||||
for (String key : asms.keySet()) {
|
||||
if (CancellableWorker.isInterrupted()) {
|
||||
throw new InterruptedException();
|
||||
}
|
||||
ASMSource asm = asms.get(key);
|
||||
if (asm instanceof DoInitActionTag) {
|
||||
DoInitActionTag doi = (DoInitActionTag) asm;
|
||||
String exportName = doi.getSwf().getCharacter(doi.getCharacterId()).getExportName();
|
||||
if (exportName != null && exportName.startsWith("__Packages.")) {
|
||||
SWF.uncache(doi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*for (String cls:result.keySet()) {
|
||||
System.err.println("class "+cls);
|
||||
|
||||
@@ -1149,6 +1149,10 @@ public final class Configuration {
|
||||
@ConfigurationDefaultBoolean(true)
|
||||
@ConfigurationCategory("script")
|
||||
public static ConfigurationItem<Boolean> showCodeCompletionOnDot = null;
|
||||
|
||||
@ConfigurationDefaultBoolean(false)
|
||||
@ConfigurationCategory("script")
|
||||
public static ConfigurationItem<Boolean> skipDetectionOfUnitializedClassFields = null;
|
||||
|
||||
private static Map<String, String> configurationDescriptions = new LinkedHashMap<>();
|
||||
private static Map<String, String> configurationTitles = new LinkedHashMap<>();
|
||||
|
||||
@@ -61,3 +61,6 @@ configurationFile.meta.showComments = Show configuration comments - set to true
|
||||
configurationFile.meta.modifiedOnly = Store modified items only in this file - set to false (and exit app again to resave) to show all.
|
||||
configurationFile.configuration = Section - Actual configuration
|
||||
configuration.removed = WARNING: This configuration was REMOVED. It is unused.
|
||||
|
||||
#after 24.0.1
|
||||
decompilationWarning.as2.noUninitializedClassFieldsDetection = WARNING: This class was decompiled without detecting uninitialized class fields.
|
||||
|
||||
@@ -62,3 +62,6 @@ configurationFile.meta.showComments = Zobrazit koment\u00e1\u0159e ke konfigurac
|
||||
configurationFile.meta.modifiedOnly = Ukl\u00e1dat do tohoto souboru pouze zm\u011bn\u011bn\u00e9 hodnoty - nastavte na false (a ukon\u010dete aplikaci pro nov\u00e9 ulo\u017een\u00ed) pro zobrazen\u00ed v\u0161eho.
|
||||
configurationFile.configuration = Sekce - Vlastn\u00ed konfigurace
|
||||
configuration.removed = VAROV\u00c1N\u00cd: Tato konfigurace byla ODSTRAN\u011aNA. Nepou\u017e\u00edv\u00e1 se.
|
||||
|
||||
#after 24.0.1
|
||||
decompilationWarning.as2.noUninitializedClassFieldsDetection = VAROV\u00c1N\u00cd: Tato t\u0159\u00edda byla dekompilov\u00e1na bez detekce neinicializovan\u00fdch pol\u00ed t\u0159\u00edd.
|
||||
|
||||
@@ -52,7 +52,18 @@ public class CommentItem extends GraphTargetItem {
|
||||
|
||||
@Override
|
||||
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) {
|
||||
writer.append("/* ");
|
||||
int commentLinesCount = 0;
|
||||
for (int i = 0; i < commentLines.length; i++) {
|
||||
if (commentLines[i] == null) {
|
||||
continue;
|
||||
}
|
||||
commentLinesCount++;
|
||||
}
|
||||
if (commentLinesCount == 1) {
|
||||
writer.append("// ");
|
||||
} else {
|
||||
writer.append("/* ");
|
||||
}
|
||||
for (int i = 0; i < commentLines.length; i++) {
|
||||
if (commentLines[i] == null) {
|
||||
continue;
|
||||
@@ -62,7 +73,10 @@ public class CommentItem extends GraphTargetItem {
|
||||
writer.newLine();
|
||||
}
|
||||
}
|
||||
return writer.append(" */");
|
||||
if (commentLinesCount > 1) {
|
||||
writer.append(" */");
|
||||
}
|
||||
return writer;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -66,6 +66,8 @@ public abstract class CancellableWorker<T> implements RunnableFuture<T> {
|
||||
private CancellableWorker parentWorker;
|
||||
|
||||
private boolean canceled = false;
|
||||
|
||||
private boolean userCancelled = false;
|
||||
|
||||
private List<Runnable> cancelListeners = new ArrayList<>();
|
||||
|
||||
@@ -188,6 +190,15 @@ public abstract class CancellableWorker<T> implements RunnableFuture<T> {
|
||||
THREAD_POOL.execute(this);
|
||||
}
|
||||
|
||||
public final boolean userCancel(boolean mayIterruptIfRunning) {
|
||||
userCancelled = true;
|
||||
return cancel(mayIterruptIfRunning);
|
||||
}
|
||||
|
||||
public boolean isUserCancelled() {
|
||||
return userCancelled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean cancel(boolean mayInterruptIfRunning) {
|
||||
canceled = true;
|
||||
|
||||
Reference in New Issue
Block a user