diff --git a/CHANGELOG.md b/CHANGELOG.md index 8c041f727..84e475115 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ All notable changes to this project will be documented in this file. - AS3 deobfuscator of registers parsing of exception targets - AS3 code with exception start/end not matching instruction boundary - AS3 deobfuscator in some cases +- #349 AS3 - better handling of declarations ### Changed - AS3 test methods separated to classes diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java index 2d94f2ddd..cabba22e9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/AVM2Code.java @@ -285,11 +285,13 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.HighlightedTextWriter; import com.jpexs.decompiler.flash.helpers.SWFDecompilerPlugin; import com.jpexs.decompiler.flash.helpers.hilight.HighlightSpecialType; +import com.jpexs.decompiler.graph.AbstractGraphTargetVisitor; import com.jpexs.decompiler.graph.Block; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphPart; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.GraphTargetVisitorInterface; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.TranslateStack; @@ -306,6 +308,7 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -1804,93 +1807,89 @@ public class AVM2Code implements Cloneable { return assignment; } - private GraphTargetItem injectDeclarations(int minreg, GraphTargetItem ti, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, ABC abc, MethodBody body) { - if (ti.value != null) { - ti.value = injectDeclarations(minreg, ti.value, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - } - //TODO: walk whole tree... some walker? - if (ti instanceof IfItem) { - ((IfItem) ti).expression = injectDeclarations(minreg, ((IfItem) ti).expression, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - } - if (ti instanceof BinaryOpItem) { - ((BinaryOpItem) ti).leftSide = injectDeclarations(minreg, ((BinaryOpItem) ti).leftSide, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - ((BinaryOpItem) ti).rightSide = injectDeclarations(minreg, ((BinaryOpItem) ti).rightSide, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - } - if (ti instanceof ForEachInAVM2Item) { - ForEachInAVM2Item fei = (ForEachInAVM2Item) ti; - if (fei.expression.object instanceof LocalRegAVM2Item) { - int reg = ((LocalRegAVM2Item) fei.expression.object).regIndex; - if (declaredRegisters[reg] == null) { - fei.expression.object = handleDeclareReg(minreg, fei.expression.object, declaredRegisters, declaredSlots, reg); + private void injectDeclarations(List items, int minreg, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, ABC abc, MethodBody body) { + for (int i = 0; i < items.size(); i++) { + GraphTargetItem currentItem = items.get(i); + List itemsOnLine = new ArrayList<>(); + itemsOnLine.add(currentItem); + currentItem.visitRecursivelyNoBlock(new AbstractGraphTargetVisitor() { + @Override + public void visit(GraphTargetItem item) { + itemsOnLine.add(item); + } + }); + + if (currentItem instanceof ForEachInAVM2Item) { + ForEachInAVM2Item fei = (ForEachInAVM2Item) currentItem; + if (fei.expression.object instanceof LocalRegAVM2Item) { + int reg = ((LocalRegAVM2Item) fei.expression.object).regIndex; + if (declaredRegisters[reg] == null) { + fei.expression.object = handleDeclareReg(minreg, fei.expression.object, declaredRegisters, declaredSlots, reg); + } + } + } + if (currentItem instanceof ForInAVM2Item) { + ForInAVM2Item fi = (ForInAVM2Item) currentItem; + if (fi.expression.object instanceof LocalRegAVM2Item) { + int reg = ((LocalRegAVM2Item) fi.expression.object).regIndex; + fi.expression.object = handleDeclareReg(minreg, fi.expression.object, declaredRegisters, declaredSlots, reg); } } - } - if (ti instanceof ForInAVM2Item) { - ForInAVM2Item fi = (ForInAVM2Item) ti; - if (fi.expression.object instanceof LocalRegAVM2Item) { - int reg = ((LocalRegAVM2Item) fi.expression.object).regIndex; - fi.expression.object = handleDeclareReg(minreg, fi.expression.object, declaredRegisters, declaredSlots, reg); - //nowdeclaredRegs.add(reg); - } - } - if (ti instanceof Block) { - Block bl = (Block) ti; - for (List s : bl.getSubs()) { - injectDeclarations(minreg, s, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - } - } - if (ti instanceof SetLocalAVM2Item) { - int reg = ((SetLocalAVM2Item) ti).regIndex; - ti = handleDeclareReg(minreg, ti, declaredRegisters, declaredSlots, reg); - return ti; - } - if (ti instanceof SetSlotAVM2Item) { - SetSlotAVM2Item ssti = (SetSlotAVM2Item) ti; - Slot sl = new Slot(ssti.scope, ssti.slotName); - if (!declaredSlots.contains(sl)) { - GraphTargetItem type = TypeItem.UNBOUNDED; - for (int t = 0; t < body.traits.traits.size(); t++) { - if (body.traits.traits.get(t).getName(abc) == sl.multiname) { - if (body.traits.traits.get(t) instanceof TraitSlotConst) { - type = PropertyAVM2Item.multinameToType(((TraitSlotConst) body.traits.traits.get(t)).type_index, abc.constants); + for (GraphTargetItem subItem : itemsOnLine) { + if (subItem instanceof SetLocalAVM2Item) { + SetLocalAVM2Item setLocal = (SetLocalAVM2Item) subItem; + int reg = setLocal.regIndex; + GraphTargetItem dec = handleDeclareReg(minreg, subItem, declaredRegisters, declaredSlots, reg); + if (dec != subItem) { //declared right now + if (subItem == currentItem) { + items.set(i, dec); + } else { + ((DeclarationAVM2Item) dec).showValue = false; + items.add(i, dec); + i++; } } } - DeclarationAVM2Item d = new DeclarationAVM2Item(ti, type); - ssti.setDeclaration(d); - declaredSlotsDec.add(d); - declaredSlots.add(sl); - return d; - //nowdeclaredSlots.add(sl); - } else { - int idx = declaredSlots.indexOf(sl); - ssti.setDeclaration(declaredSlotsDec.get(idx)); + if (subItem instanceof SetSlotAVM2Item) { + SetSlotAVM2Item ssti = (SetSlotAVM2Item) subItem; + Slot sl = new Slot(ssti.scope, ssti.slotName); + if (!declaredSlots.contains(sl)) { + GraphTargetItem type = TypeItem.UNBOUNDED; + for (int t = 0; t < body.traits.traits.size(); t++) { + if (body.traits.traits.get(t).getName(abc) == sl.multiname) { + if (body.traits.traits.get(t) instanceof TraitSlotConst) { + type = PropertyAVM2Item.multinameToType(((TraitSlotConst) body.traits.traits.get(t)).type_index, abc.constants); + } + } + } + DeclarationAVM2Item d = new DeclarationAVM2Item(subItem, type); + ssti.setDeclaration(d); + declaredSlotsDec.add(d); + declaredSlots.add(sl); + + if (subItem == currentItem) { + items.set(i, d); + } else { + d.showValue = false; + items.add(i, d); + i++; + } + + } else { + int idx = declaredSlots.indexOf(sl); + ssti.setDeclaration(declaredSlotsDec.get(idx)); + } + } + } + + if (currentItem instanceof Block) { + Block blk = (Block) currentItem; + for (List sub : blk.getSubs()) { + injectDeclarations(sub, minreg, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); + } } } - return ti; - } - - private void injectDeclarations(int minreg, List list, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, ABC abc, MethodBody body) { - //List nowdeclaredRegs=new ArrayList<>(); - //List nowdeclaredSlots=new ArrayList<>(); - for (int i = 0; i < list.size(); i++) { - GraphTargetItem ti = list.get(i); - GraphTargetItem ti2 = injectDeclarations(minreg, ti, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); - if (ti != ti2) { - list.set(i, ti2); - } - } - - /* - //undeclare registers at the end of the block? - for(int reg:nowdeclaredRegs){ - declaredRegisters[reg] = false; - } - - for(Slot s:nowdeclaredSlots){ - declaredSlots.remove(s); - }*/ } public List toGraphTargetItems(boolean thisHasDefaultToPrimitive, ConvertData convertData, String path, int methodIndex, boolean isStatic, int scriptIndex, int classIndex, ABC abc, MethodBody body, HashMap localRegNames, ScopeStack scopeStack, int initializerType, List fullyQualifiedNames, List initTraits, int staticOperation, HashMap localRegAssigmentIps, HashMap> refs) throws InterruptedException { @@ -2000,7 +1999,7 @@ public class AVM2Code implements Cloneable { // //int minreg = abc.method_info.get(body.method_info).getMaxReservedReg() + 1; - injectDeclarations(1, list, d, new ArrayList<>(), new ArrayList<>(), abc, body); + injectDeclarations(list, 1, d, new ArrayList<>(), new ArrayList<>(), abc, body); int lastPos = list.size() - 1; if (lastPos < 0) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java index b91a26aa6..3416ad192 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java @@ -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.model.clauses; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; @@ -40,6 +41,8 @@ public class DeclarationAVM2Item extends AVM2Item { public GraphTargetItem type; + public boolean showValue = true; + public DeclarationAVM2Item(GraphTargetItem assignment, GraphTargetItem type) { super(assignment.getSrc(), assignment.getLineStartItem(), assignment.getPrecedence()); this.type = type; @@ -108,8 +111,11 @@ public class DeclarationAVM2Item extends AVM2Item { writer.append(localName); writer.append(":"); type.appendTry(writer, localData); - writer.append(" = "); - return val.toString(writer, localData); + if (showValue) { + writer.append(" = "); + val.toString(writer, localData); + } + return writer; } if (assignment instanceof SetSlotAVM2Item) { SetSlotAVM2Item ssti = (SetSlotAVM2Item) assignment; @@ -136,8 +142,11 @@ public class DeclarationAVM2Item extends AVM2Item { writer.append(":"); type.appendTry(writer, localData); - writer.append(" = "); - return val.toString(writer, localData); + if (showValue) { + writer.append(" = "); + val.toString(writer, localData); + } + return writer; } writer.append("var "); return assignment.toString(writer, localData); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForEachInAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForEachInAVM2Item.java index b927dc580..9e148343e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForEachInAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForEachInAVM2Item.java @@ -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.model.clauses; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -62,6 +63,12 @@ public class ForEachInAVM2Item extends LoopItem implements Block { visitor.visitAll(commands); } + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + visitor.visit(expression); + } + + public ForEachInAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, Loop loop, InAVM2Item expression, List commands) { super(instruction, lineStartIns, loop); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForInAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForInAVM2Item.java index a1ae31a99..5d488eb65 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForInAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/ForInAVM2Item.java @@ -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.model.clauses; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -64,6 +65,12 @@ public class ForInAVM2Item extends LoopItem implements Block { visitor.visitAll(commands); } + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + visitor.visit(expression); + } + + public ForInAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, Loop loop, InAVM2Item expression, List commands) { super(instruction, lineStartIns, loop); if (!commands.isEmpty()) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java index 15dd6b52e..ce52b429f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/TryAVM2Item.java @@ -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.model.clauses; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -88,6 +89,12 @@ public class TryAVM2Item extends AVM2Item implements Block { } } + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + + } + + public TryAVM2Item(List tryCommands, List catchExceptions, List> catchCommands, List finallyCommands, String finCatchName) { super(null, null, NOPRECEDENCE); this.tryCommands = tryCommands; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java index 5df46b966..e2ed1dfa2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/parser/script/ClassAVM2Item.java @@ -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.decompiler.flash.abc.avm2.model.AVM2Item; @@ -20,6 +21,7 @@ import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.Block; import com.jpexs.decompiler.graph.DottedChain; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.GraphTargetVisitorInterface; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.decompiler.graph.model.UnboundedTypeItem; @@ -74,6 +76,12 @@ public class ClassAVM2Item extends AVM2Item implements Block { return ret; } + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + + } + + public ClassAVM2Item(List>> metadata, List importedClasses, NamespaceItem pkg, List openedNamespaces, boolean isFinal, boolean isDynamic, String className, GraphTargetItem extendsOp, List implementsOp, List cinit, boolean staticInitActivation, List cinitVariables, GraphTargetItem iinit, List iinitVariables, List traits, boolean iinitActivation) { super(null, null, NOPRECEDENCE); this.metadata = metadata; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ClassActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ClassActionItem.java index a9cb724b0..8fe844112 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ClassActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ClassActionItem.java @@ -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.action.model.clauses; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -29,6 +30,7 @@ import com.jpexs.decompiler.graph.Block; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.GraphTargetVisitorInterface; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -63,6 +65,12 @@ public class ClassActionItem extends ActionItem implements Block { return ret; } + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + + } + + public ClassActionItem(GraphTargetItem className, GraphTargetItem extendsOp, List implementsOp, List> traits, List traitsStatic) { super(null, null, NOPRECEDENCE); this.className = className; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java index adcfc8ce4..ccde62107 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/ForInActionItem.java @@ -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.action.model.clauses; import com.jpexs.decompiler.flash.SWF; @@ -35,6 +36,7 @@ import com.jpexs.decompiler.graph.Block; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.GraphTargetVisitorInterface; import com.jpexs.decompiler.graph.Loop; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.model.ContinueItem; @@ -66,6 +68,22 @@ public class ForInActionItem extends LoopActionItem implements Block { return ret; } + @Override + public void visit(GraphTargetVisitorInterface visitor) { + visitor.visit(variableName); + visitor.visit(enumVariable); + visitor.visitAll(commands); + } + + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + visitor.visit(variableName); + visitor.visit(enumVariable); + } + + + + public ForInActionItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, Loop loop, GraphTargetItem variableName, GraphTargetItem enumVariable, List commands) { super(instruction, lineStartIns, loop); this.variableName = variableName; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/IfFrameLoadedActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/IfFrameLoadedActionItem.java index 9aeb17593..51508c521 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/IfFrameLoadedActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/IfFrameLoadedActionItem.java @@ -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.action.model.clauses; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -24,6 +25,7 @@ import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.Graph; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.GraphTargetVisitorInterface; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -46,6 +48,19 @@ public class IfFrameLoadedActionItem extends ActionItem implements Block { this.frame = frame; } + @Override + public void visit(GraphTargetVisitorInterface visitor) { + visitor.visit(frame); + visitor.visitAll(actions); + } + + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + visitor.visit(frame); + } + + + @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { writer.append("ifFrameLoaded"); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/TryActionItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/TryActionItem.java index 32db4f8d2..c5623ac54 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/TryActionItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/action/model/clauses/TryActionItem.java @@ -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.action.model.clauses; import com.jpexs.decompiler.flash.SWF; @@ -39,6 +40,7 @@ import com.jpexs.decompiler.graph.Block; import com.jpexs.decompiler.graph.CompilationException; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.GraphTargetVisitorInterface; import com.jpexs.decompiler.graph.SourceGenerator; import com.jpexs.decompiler.graph.model.ContinueItem; import com.jpexs.decompiler.graph.model.LocalData; @@ -76,6 +78,26 @@ public class TryActionItem extends ActionItem implements Block { return ret; } + @Override + public void visit(GraphTargetVisitorInterface visitor) { + if (tryCommands != null) { + visitor.visitAll(tryCommands); + } + for (List cc : catchCommands) { + visitor.visitAll(cc); + } + if (finallyCommands != null) { + visitor.visitAll(finallyCommands); + } + } + + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + + } + + + public TryActionItem(List tryCommands, List catchExceptionNames, List catchExceptionTypes, List> catchCommands, List finallyCommands) { super(null, null, NOPRECEDENCE); this.tryCommands = tryCommands; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java index 5cff966e0..27b2b1161 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -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.graph; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -534,12 +535,30 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { }); } + public final void visitRecursivelyNoBlock(GraphTargetVisitorInterface visitor) { + Set visitedItems = new HashSet<>(); + visitNoBlock(new AbstractGraphTargetVisitor() { + @Override + public void visit(GraphTargetItem item) { + if (item != null && !visitedItems.contains(item)) { + visitedItems.add(item); + visitor.visit(item); + item.visitNoBlock(this); + } + } + }); + } + public void visit(GraphTargetVisitorInterface visitor) { if (value != null) { visitor.visit(value); } } + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + visit(visitor); + } + public abstract GraphTargetItem returnType(); @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DoWhileItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DoWhileItem.java index 8ca3cbfab..88b43cedc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DoWhileItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/DoWhileItem.java @@ -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.graph.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -69,6 +70,14 @@ public class DoWhileItem extends LoopItem implements Block { } } + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + if (expression != null) { + visitor.visitAll(expression); + } + } + + public DoWhileItem(GraphSourceItem src, GraphSourceItem lineStartIns, Loop loop, List commands, List expression) { super(src, lineStartIns, loop); this.expression = expression; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ForItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ForItem.java index 7b739f1d4..24815aa0b 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ForItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/ForItem.java @@ -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.graph.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -75,6 +76,12 @@ public class ForItem extends LoopItem implements Block { } } + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + visitor.visit(expression); + } + + public ForItem(GraphSourceItem src, GraphSourceItem lineStartIns, Loop loop, List firstCommands, GraphTargetItem expression, List finalCommands, List commands) { super(src, lineStartIns, loop); this.firstCommands = firstCommands; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/GotoItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/GotoItem.java index 05249d319..a2b70eb17 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/GotoItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/GotoItem.java @@ -12,13 +12,15 @@ * 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.graph.model; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.graph.Block; import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.GraphTargetVisitorInterface; import com.jpexs.decompiler.graph.TypeItem; import java.util.ArrayList; import java.util.List; @@ -106,4 +108,15 @@ public class GotoItem extends GraphTargetItem implements Block { } return ret; } + + @Override + public void visit(GraphTargetVisitorInterface visitor) { + if (targetCommands != null) { + visitor.visitAll(targetCommands); + } + } + + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java index 7111ebb87..6edd2bef2 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/IfItem.java @@ -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.graph.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -72,6 +73,12 @@ public class IfItem extends GraphTargetItem implements Block { } } + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + visitor.visit(expression); + } + + public IfItem(GraphSourceItem src, GraphSourceItem lineStartIns, GraphTargetItem expression, List onTrue, List onFalse) { super(src, lineStartIns, NOPRECEDENCE); this.expression = expression; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwitchItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwitchItem.java index 0202ef4e1..4cd440d6d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwitchItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/SwitchItem.java @@ -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.graph.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -62,6 +63,13 @@ public class SwitchItem extends LoopItem implements Block { } } + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + visitor.visit(switchedObject); + visitor.visitAll(caseValues); + } + + public SwitchItem(GraphSourceItem instruction, GraphSourceItem lineStartIns, Loop loop, GraphTargetItem switchedObject, List caseValues, List> caseCommands, List valuesMapping) { super(instruction, lineStartIns, loop); this.switchedObject = switchedObject; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/WhileItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/WhileItem.java index a0ee240ca..c7e2d0bf8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/WhileItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/WhileItem.java @@ -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.graph.model; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; @@ -64,6 +65,14 @@ public class WhileItem extends LoopItem implements Block { } } + @Override + public void visitNoBlock(GraphTargetVisitorInterface visitor) { + if (expression != null) { + visitor.visitAll(expression); + } + } + + public WhileItem(GraphSourceItem src, GraphSourceItem lineStartIns, Loop loop, List expression, List commands) { super(src, lineStartIns, loop); this.expression = expression; diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java index c7d4ce8e0..124102780 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java @@ -16,6 +16,17 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT addSwf("assembled", "testdata/as3_assembled/bin/as3_assembled.swf"); } + @Test + public void testDeclareReg() { + decompileMethod("assembled", "testDeclareReg", "var _loc3_:*;\r\n" + + "with(_loc3_ = other)\r\n" + + "{\r\n" + + "\r\n" + + "trace(\"hey\");\r\n" + + "}\r\n", + false); + } + @Test public void testDoubleDup() { decompileMethod("assembled", "testDoubleDup", "var _loc10_:Rectangle = myprop(_loc5_);\r\n" @@ -25,7 +36,8 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT @Test public void testDup() { - decompileMethod("assembled", "testDup", "return 1 - (var _loc1_:Number = 1 - _loc1_ / _loc4_) * _loc1_;\r\n", + decompileMethod("assembled", "testDup", "var _loc1_:Number;\r\n" + + "return 1 - (_loc1_ = 1 - _loc1_ / _loc4_) * _loc1_;\r\n", false); } @@ -90,6 +102,7 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT @Test public void testSetSlotDup() { decompileMethod("assembled", "testSetSlotDup", "var _loc5_:int = 5;\r\n" + + "var myslot:int;\r\n" + "myname.somemethod(\"okay\",myslot = _loc5_);\r\n" + "myname.start();\r\n", false); @@ -97,7 +110,8 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT @Test public void testSetSlotFindProperty() { - decompileMethod("assembled", "testSetSlotFindProperty", "return var myprop:int = 50;\r\n", + decompileMethod("assembled", "testSetSlotFindProperty", "var myprop:int;\r\n" + + "return myprop = 50;\r\n", false); } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java index 27b5a53ad..625b722ae 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicAirDecompileTest.java @@ -743,7 +743,6 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile @Test public void testInc2() { decompileMethod("classic_air", "testInc2", "var a:* = [1];\r\n" - + "a[this.getInt()]++;\r\n" + "var d:* = a[this.getInt()]++;\r\n" + "var e:* = ++a[this.getInt()];\r\n" + "a[this.getInt()]++;\r\n" @@ -942,7 +941,8 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile public void testNamedAnonFunctions() { decompileMethod("classic_air", "testNamedAnonFunctions", "var test:* = new function():*\r\n" + "{\r\n" - + "return var testFunc:Function = function(param1:*, param2:int, param3:Array):Boolean\r\n" + + "var testFunc:Function;\r\n" + + "return testFunc = function(param1:*, param2:int, param3:Array):Boolean\r\n" + "{\r\n" + "return (param1 as TestClass2).attrib1 == 5;\r\n" + "};\r\n" diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java index 8fda2670f..f1379e4b8 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3ClassicDecompileTest.java @@ -734,7 +734,6 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes @Test public void testInc2() { decompileMethod("classic", "testInc2", "var a:* = [1];\r\n" - + "++a[this.getInt()];\r\n" + "var d:* = a[this.getInt()]++;\r\n" + "var e:* = ++a[this.getInt()];\r\n" + "++a[this.getInt()];\r\n" diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc index e1d46d642..b63178b10 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc and b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc differ diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm index ce430830f..9f530cdd3 100644 --- a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm @@ -16,5 +16,6 @@ program #include "tests/TestDup.script.asasm" #include "tests/TestSwitchDefault.script.asasm" #include "tests/TestSwitch.script.asasm" + #include "tests/TestDeclareReg.script.asasm" ; place to add next end ; program diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestDeclareReg.class.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestDeclareReg.class.asasm new file mode 100644 index 000000000..4e74e41f7 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestDeclareReg.class.asasm @@ -0,0 +1,76 @@ +class + refid "tests:TestDeclareReg" + instance QName(PackageNamespace("tests"), "TestDeclareReg") + extends QName(PackageNamespace(""), "Object") + flag SEALED + flag PROTECTEDNS + protectedns ProtectedNamespace("tests:TestDeclareReg") + iinit + refid "tests:TestDeclareReg/instance/init" + body + maxstack 1 + localcount 1 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + + getlocal0 + constructsuper 0 + + returnvoid + end ; code + end ; body + end ; method + trait method QName(PackageNamespace(""), "run") + method + refid "tests:TestDeclareReg/instance/run" + returns QName(PackageNamespace(""), "void") + body + maxstack 2 + localcount 4 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + newactivation + dup + setlocal2 + pushscope + getscopeobject 1 + getslot 1 + dup + setlocal3 + pushwith + findpropstrict QName(PackageNamespace(""),"trace") + pushstring "hey" + callpropvoid QName(PackageNamespace(""),"trace"), 1 + popscope + returnvoid + end ; code + trait slot QName(PackageInternalNs("something"),"other") + slotid 1 + type QName(PackageNamespace(""),"XML") + end ; trait + end ; body + end ; method + end ; trait + end ; instance + cinit + refid "tests:TestDeclareReg/class/init" + body + maxstack 1 + localcount 1 + initscopedepth 3 + maxscopedepth 4 + code + getlocal0 + pushscope + + returnvoid + end ; code + end ; body + end ; method +end ; class diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestDeclareReg.script.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestDeclareReg.script.asasm new file mode 100644 index 000000000..51d62e908 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestDeclareReg.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestDeclareReg/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestDeclareReg", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestDeclareReg"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestDeclareReg" + popscope + initproperty QName(PackageNamespace("tests"), "TestDeclareReg") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestDeclareReg") + #include "TestDeclareReg.class.asasm" + end ; trait +end ; script diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf b/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf index 70b9c3471..eb826ef39 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf and b/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf index 69821c54b..eae1d8d81 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.air.swf differ diff --git a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf index 6ad6c6b53..77ee077d1 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf and b/libsrc/ffdec_lib/testdata/as3_new/bin/as3_new.flex.swf differ