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:
Jindra Petřík
2025-07-01 19:50:18 +02:00
parent 8a3cbf9e2d
commit 5ffc71848b
22 changed files with 225 additions and 37 deletions
@@ -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);