Fixed: #2291 AS1/2 Incorrect var keyword placement causing registers to compile wrong

This commit is contained in:
Jindra Petřík
2024-09-23 21:52:25 +02:00
parent 2976829642
commit 236126dc84
10 changed files with 80 additions and 34 deletions
@@ -2775,7 +2775,7 @@ public class AVM2Code implements Cloneable {
//Check whether the command references internal traits of other package
ti.visitRecursively(new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
if (item instanceof GetSlotAVM2Item) {
GetSlotAVM2Item gs = (GetSlotAVM2Item) item;
if ((gs.slotObject instanceof GlobalAVM2Item) && (initializerType == GraphTextWriter.TRAIT_SCRIPT_INITIALIZER)) {
@@ -2798,6 +2798,7 @@ public class AVM2Code implements Cloneable {
}
}
}
return true;
}
});
@@ -2277,9 +2277,9 @@ public class AVM2Graph extends Graph {
private boolean handled = false;
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
if (handled) {
return;
return false;
}
if ((item instanceof NextNameAVM2Item) || (item instanceof NextValueAVM2Item)) {
handled = true;
@@ -2293,7 +2293,9 @@ public class AVM2Graph extends Graph {
nn.localReg = hn.index;
kindRef.setVal(2);
}
return false;
}
return true;
}
});
@@ -50,6 +50,7 @@ import com.jpexs.decompiler.flash.action.swf4.RegisterNumber;
import com.jpexs.decompiler.flash.action.swf5.ActionConstantPool;
import com.jpexs.decompiler.flash.action.swf5.ActionDefineFunction;
import com.jpexs.decompiler.flash.action.swf5.ActionEquals2;
import com.jpexs.decompiler.flash.action.swf5.ActionStoreRegister;
import com.jpexs.decompiler.flash.action.swf5.ActionWith;
import com.jpexs.decompiler.flash.action.swf7.ActionDefineFunction2;
import com.jpexs.decompiler.flash.action.swf7.ActionTry;
@@ -58,9 +59,11 @@ import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.flash.ecma.Null;
import com.jpexs.decompiler.flash.ecma.Undefined;
import com.jpexs.decompiler.flash.exporters.modes.ScriptExportMode;
import com.jpexs.decompiler.flash.helpers.CodeFormatting;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.flash.helpers.NulWriter;
import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin;
import com.jpexs.decompiler.flash.helpers.StringBuilderTextWriter;
import com.jpexs.decompiler.flash.tags.DoInitActionTag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.graph.Graph;
@@ -1243,7 +1246,7 @@ public abstract class Action implements GraphSourceItem {
loopip:
while (ip <= end) {
long addr = ip2adr(actions, ip);
long addr = ip2adr(actions, ip);
if (ip > end) {
break;
}
@@ -1254,7 +1257,7 @@ public abstract class Action implements GraphSourceItem {
if (Configuration.simplifyExpressions.get()) {
stack.simplify();
}
Action action = actions.get(ip);
Action action = actions.get(ip);
if (action.isIgnored()) {
ip++;
continue;
@@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.action.model.SetTypeActionItem;
import com.jpexs.decompiler.flash.action.model.StoreRegisterActionItem;
import com.jpexs.decompiler.flash.action.model.TemporaryRegister;
import com.jpexs.decompiler.flash.action.model.TemporaryRegisterMark;
import com.jpexs.decompiler.flash.action.model.TraceActionItem;
import com.jpexs.decompiler.flash.action.model.clauses.ForInActionItem;
import com.jpexs.decompiler.flash.action.model.clauses.TellTargetActionItem;
import com.jpexs.decompiler.flash.action.model.operations.EqActionItem;
@@ -58,6 +59,7 @@ import com.jpexs.decompiler.graph.GraphSource;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphSourceItemContainer;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.GraphTargetVisitorInterface;
import com.jpexs.decompiler.graph.Loop;
import com.jpexs.decompiler.graph.SecondPassData;
import com.jpexs.decompiler.graph.StopPartKind;
@@ -74,10 +76,12 @@ import com.jpexs.decompiler.graph.model.SwitchItem;
import com.jpexs.decompiler.graph.model.TrueItem;
import com.jpexs.decompiler.graph.model.WhileItem;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.LinkedIdentityHashSet;
import com.jpexs.helpers.Reference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -215,13 +219,13 @@ public class ActionGraph extends Graph {
* @return List of graph target items
* @throws InterruptedException On interrupt
*/
public static List<GraphTargetItem> translateViaGraph(Map<String, Map<String, Trait>> uninitializedClassTraits, SecondPassData secondPassData, boolean insideDoInitAction, boolean insideFunction, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, List<Action> code, int version, int staticOperation, String path, String charset) throws InterruptedException {
public static List<GraphTargetItem> translateViaGraph(Map<String, Map<String, Trait>> uninitializedClassTraits, SecondPassData secondPassData, boolean insideDoInitAction, boolean insideFunction, HashMap<Integer, String> registerNames, HashMap<String, GraphTargetItem> variables, HashMap<String, GraphTargetItem> functions, List<Action> code, int version, int staticOperation, String path, String charset) throws InterruptedException {
ActionGraph g = new ActionGraph(uninitializedClassTraits, path, insideDoInitAction, insideFunction, code, registerNames, variables, functions, version, charset);
ActionLocalData localData = new ActionLocalData(secondPassData, insideDoInitAction, registerNames, uninitializedClassTraits);
g.init(localData);
return g.translate(localData, staticOperation, path);
}
/**
* Final process stack. Override this method to provide custom behavior.
*
@@ -621,7 +625,7 @@ public class ActionGraph extends Graph {
ActionScript2ClassDetector detector = new ActionScript2ClassDetector();
detector.checkClass(uninitializedClassTraits, ret, ((ActionGraphSource) code).getVariables(), path);
}
makeDefineRegistersUp(ret);
makeDefineRegistersUp(ret, new HashSet<>());
return ret;
}
@@ -640,52 +644,73 @@ public class ActionGraph extends Graph {
trace("x");
}
It also makes sure that var keyword is on the first occurrence of that register.
*/
/**
* Makes define registers up.
*
* @param list List of GraphTargetItems
* @param definedRegisters Defined registers
*/
private void makeDefineRegistersUp(List<GraphTargetItem> list) {
private void makeDefineRegistersUp(List<GraphTargetItem> list, Set<Integer> definedRegisters) {
for (int i = 0; i < list.size(); i++) {
final int fi = i;
GraphTargetItem ti = list.get(i);
Reference<Integer> ri = new Reference<>(i);
if (ti instanceof TemporaryRegister) {
continue;
}
Set<GraphTargetItem> visitedItems = new HashSet<>();
ti.visitNoBlock(new AbstractGraphTargetVisitor() {
Set<GraphTargetItem> visitedItems = new LinkedIdentityHashSet<>();
GraphTargetVisitorInterface visitor = new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
if (item != null && !visitedItems.contains(item)) {
visitedItems.add(item);
if (item instanceof TemporaryRegister) {
return;
return true;
}
//can has definition in for in...
if ((ti instanceof ForInActionItem) && (item == ((ForInActionItem) ti).variableName)) {
return;
return true;
}
if (item instanceof StoreRegisterActionItem) {
StoreRegisterActionItem sr = (StoreRegisterActionItem) item;
if (sr.define) {
list.add(fi, new StoreRegisterActionItem(null, null, sr.register, new DirectValueActionItem(Null.INSTANCE), true));
sr.define = false;
sr.define = !definedRegisters.contains(sr.register.number);
definedRegisters.add(sr.register.number);
if (sr.define && sr != ti) {
list.add(ri.getVal(), new StoreRegisterActionItem(null, null, sr.register, new DirectValueActionItem(Null.INSTANCE), true));
sr.define = false;
ri.setVal(ri.getVal() + 1);
}
}
if (item instanceof FunctionActionItem) {
return false;
}
item.visitNoBlock(this);
}
return true;
}
});
};
if (ti instanceof StoreRegisterActionItem) {
StoreRegisterActionItem sr = (StoreRegisterActionItem) ti;
sr.define = !definedRegisters.contains(sr.register.number);
definedRegisters.add(sr.register.number);
}
ti.visitNoBlock(visitor);
//visitor.visit(ti);
//ti.visitRecursively(visitor);
i = ri.getVal();
if (ti instanceof Block) {
Block b = (Block) ti;
for (List<GraphTargetItem> items : b.getSubs()) {
makeDefineRegistersUp(items);
makeDefineRegistersUp(items, definedRegisters);
}
}
}
@@ -678,7 +678,7 @@ public class ActionScript2ClassDetector {
AbstractGraphTargetVisitor visitor = new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
if (item instanceof ReturnActionItem) {
ReturnActionItem ret = (ReturnActionItem) item;
if (ret.value instanceof DirectValueActionItem) {
@@ -688,6 +688,7 @@ public class ActionScript2ClassDetector {
}
}
}
return true;
}
};
for (GraphTargetItem ti : func.actions) {
@@ -790,7 +791,7 @@ public class ActionScript2ClassDetector {
AbstractGraphTargetVisitor visitor = new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
if (item instanceof ReturnActionItem) {
ReturnActionItem ret = (ReturnActionItem) item;
if (ret.value instanceof DirectValueActionItem) {
@@ -800,6 +801,7 @@ public class ActionScript2ClassDetector {
}
}
}
return true;
}
};
for (GraphTargetItem ti : ((FunctionActionItem) constructor).actions) {
@@ -301,7 +301,7 @@ public class UninitializedClassFieldsDetector {
if (value instanceof GraphTargetItem) {
AbstractGraphTargetVisitor visitor = new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
List<String> path = getFullPath(item);
if (path != null) {
List<String> parent = new ArrayList<>(path);
@@ -319,6 +319,7 @@ public class UninitializedClassFieldsDetector {
}
}
}
return true;
}
};
visitor.visit(value);
@@ -339,7 +340,7 @@ public class UninitializedClassFieldsDetector {
for (GraphTargetItem item : tree) {
AbstractGraphTargetVisitor visitor = new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
if ((item instanceof SetMemberActionItem)
|| (item instanceof CallMethodActionItem)
|| (item instanceof NewMethodActionItem)
@@ -364,6 +365,7 @@ public class UninitializedClassFieldsDetector {
}
}
}
return true;
}
};
visitor.visit(item);
@@ -35,9 +35,10 @@ public abstract class AbstractGraphTargetVisitor implements GraphTargetVisitorIn
* Visits a graph target item.
*
* @param item Graph target item
* @return True if continue
*/
@Override
public abstract void visit(GraphTargetItem item);
public abstract boolean visit(GraphTargetItem item);
/**
* Visits all graph target items.
@@ -41,6 +41,7 @@ import com.jpexs.decompiler.graph.model.FalseItem;
import com.jpexs.decompiler.graph.model.LocalData;
import com.jpexs.decompiler.graph.model.NotItem;
import com.jpexs.decompiler.graph.model.TrueItem;
import com.jpexs.helpers.LinkedIdentityHashSet;
import com.jpexs.helpers.Reference;
import java.io.Serializable;
import java.util.ArrayList;
@@ -624,10 +625,11 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
Reference<Boolean> ref = new Reference<>(false);
visitRecursively(new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
if (item.hasSideEffect()) {
ref.setVal(Boolean.TRUE);
}
return true;
}
});
return ref.getVal();
@@ -923,10 +925,11 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
List<GraphTargetItem> ret = new ArrayList<>();
visit(new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
if (item != null) {
ret.add(item);
}
return true;
}
});
return ret;
@@ -941,8 +944,9 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
Set<GraphTargetItem> ret = new HashSet<>();
visitRecursively(new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
ret.add(item);
return true;
}
});
return ret;
@@ -954,15 +958,17 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
* @param visitor Visitor
*/
public final void visitRecursively(GraphTargetVisitorInterface visitor) {
Set<GraphTargetItem> visitedItems = new HashSet<>();
Set<GraphTargetItem> visitedItems = new LinkedIdentityHashSet<>();
visit(new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
if (item != null && !visitedItems.contains(item)) {
visitedItems.add(item);
visitor.visit(item);
item.visit(this);
if (visitor.visit(item)) {
item.visit(this);
}
}
return true;
}
});
}
@@ -978,7 +984,7 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
parentStack.add(this);
visitNoBlock(new AbstractGraphTargetVisitor() {
@Override
public void visit(GraphTargetItem item) {
public boolean visit(GraphTargetItem item) {
if (item != null && !visitedItems.contains(item)) {
visitedItems.add(item);
visitor.visit(item, parentStack);
@@ -986,6 +992,7 @@ public abstract class GraphTargetItem implements Serializable, Cloneable {
item.visitNoBlock(this);
parentStack.pop();
}
return true;
}
});
}
@@ -29,8 +29,9 @@ public interface GraphTargetVisitorInterface {
* Visits a graph target item.
*
* @param item Graph target item
* @return True if continue
*/
public void visit(GraphTargetItem item);
public boolean visit(GraphTargetItem item);
/**
* Visits all graph target items.