Fixed: AS3 getslot/setslot, getglobalscope instruction

This commit is contained in:
Jindra Petřík
2021-02-09 22:15:12 +01:00
parent 485dabc2d2
commit fcd39050b7
34 changed files with 473 additions and 178 deletions

View File

@@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file.
- AS3 break loop in catch clause
- AS3 inner functions scope (setslot/getslot)
- AS3 p-code traits of bodys of inner methods
- AS3 getslot/setslot, getglobalscope instruction
## [13.0.0] - 2021-02-08
### Added

View File

@@ -254,6 +254,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NullAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.ReturnVoidAVM2Item;
@@ -1875,32 +1876,34 @@ public class AVM2Code implements Cloneable {
}
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);
if (ssti.scope instanceof NewActivationAVM2Item) {
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);
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++;
}
if (subItem == currentItem) {
items.set(i, d);
} else {
d.showValue = false;
items.add(i, d);
i++;
int idx = declaredSlots.indexOf(sl);
ssti.setDeclaration(declaredSlotsDec.get(idx));
}
} else {
int idx = declaredSlots.indexOf(sl);
ssti.setDeclaration(declaredSlotsDec.get(idx));
}
}
}

View File

@@ -32,6 +32,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.ClassAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.ThisAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item;
@@ -40,6 +41,7 @@ import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitWithSlot;
import com.jpexs.decompiler.flash.abc.types.traits.Traits;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.GraphSourceItem;
@@ -325,49 +327,51 @@ public abstract class InstructionDefinition implements Serializable {
return localData.code.adr2pos(src.getAddress());
}
protected Multiname searchSlotName(int slotIndex, AVM2LocalData localData, GraphTargetItem obj) {
return searchSlotName(slotIndex, localData, obj, -1);
protected static Multiname searchSlotName(int slotIndex, AVM2LocalData localData, GraphTargetItem obj, Reference<GraphTargetItem> realObj) {
return searchSlotName(slotIndex, localData, obj, -1, realObj);
}
private Multiname searchSlotName(int slotIndex, AVM2LocalData localData, GraphTargetItem obj, int multiNameIndex) {
private static Multiname searchSlotName(int slotIndex, AVM2LocalData localData, GraphTargetItem obj, int multiNameIndex, Reference<GraphTargetItem> realObj) {
if ((obj instanceof ExceptionAVM2Item) && (multiNameIndex == -1 || ((ExceptionAVM2Item) obj).exception.name_index == multiNameIndex)) {
return localData.getConstants().getMultiname(((ExceptionAVM2Item) obj).exception.name_index);
} else if ((obj instanceof ThisAVM2Item) || (obj instanceof ClassAVM2Item)) {
List<Trait> traits = localData.getScriptInfo().get(localData.scriptIndex).traits.traits;
for (int t = 0; t < traits.size(); t++) {
Trait trait = traits.get(t);
if (trait instanceof TraitWithSlot) {
if (multiNameIndex == -1 || trait.name_index == multiNameIndex) {
if (((TraitWithSlot) trait).getSlotIndex() == slotIndex) {
return trait.getName(localData.abc);
}
}
}
}
} else if (obj instanceof NewActivationAVM2Item) {
MethodBody body = localData.methodBody;
List<Trait> traits = body.traits.traits;
for (int t = 0; t < traits.size(); t++) {
Trait trait = traits.get(t);
if (trait instanceof TraitWithSlot) {
if (multiNameIndex == -1 || trait.name_index == multiNameIndex) {
if (((TraitWithSlot) trait).getSlotIndex() == slotIndex) {
return trait.getName(localData.abc);
}
}
}
}
} else if (obj instanceof FindPropertyAVM2Item) {
}
if (obj instanceof FindPropertyAVM2Item) {
FindPropertyAVM2Item findProp = (FindPropertyAVM2Item) obj;
for (GraphTargetItem item : localData.scopeStack) {
Multiname ret = searchSlotName(slotIndex, localData, item, ((FullMultinameAVM2Item) findProp.propertyName).multinameIndex);
Multiname ret = searchSlotName(slotIndex, localData, item, ((FullMultinameAVM2Item) findProp.propertyName).multinameIndex, realObj);
if (ret != null) {
return ret;
}
}
return null;
}
Traits traits = null;
if (obj instanceof NewActivationAVM2Item) {
traits = localData.methodBody.traits;
} else if (obj instanceof ThisAVM2Item) {
traits = localData.abc.instance_info.get(localData.classIndex).instance_traits;
} else if (obj instanceof ClassAVM2Item) {
traits = localData.abc.class_info.get(localData.classIndex).static_traits;
} else if (obj instanceof GlobalAVM2Item) {
traits = localData.abc.script_info.get(localData.scriptIndex).traits;
}
if (traits != null) {
for (int t = 0; t < traits.traits.size(); t++) {
Trait trait = traits.traits.get(t);
if (trait instanceof TraitWithSlot) {
if (multiNameIndex == -1 || trait.name_index == multiNameIndex) {
if (((TraitWithSlot) trait).getSlotIndex() == slotIndex) {
realObj.setVal(obj);
return trait.getName(localData.abc);
}
}
}
}
}
return null;
}
}

View File

@@ -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.instructions;
import com.jpexs.decompiler.flash.abc.ABC;
@@ -36,8 +37,6 @@ import java.util.Stack;
*/
public interface SetTypeIns {
public abstract String getObject(Stack<AVM2Item> stack, ABC abc, AVM2Instruction ins, List<AVM2Item> output, MethodBody body, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames) throws InterruptedException;
public static void handleResult(GraphTargetItem value, TranslateStack stack, List<GraphTargetItem> output, AVM2LocalData localData, GraphTargetItem result, int regId) {
GraphTargetItem notCoercedValue = value;
if ((value instanceof CoerceAVM2Item) || (value instanceof ConvertAVM2Item)) {

View File

@@ -23,6 +23,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.NewFunctionAVM2Item;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.ScopeStack;
import com.jpexs.decompiler.graph.TranslateStack;
import java.util.List;
@@ -39,7 +40,7 @@ public class NewFunctionIns extends InstructionDefinition {
@Override
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, String path) {
int methodIndex = ins.operands[0];
NewFunctionAVM2Item function = new NewFunctionAVM2Item(ins, localData.lineStartInstruction, "", path, false, localData.scriptIndex, localData.classIndex, localData.abc, localData.fullyQualifiedNames, methodIndex, localData.scopeStack);
NewFunctionAVM2Item function = new NewFunctionAVM2Item(ins, localData.lineStartInstruction, "", path, false, localData.scriptIndex, localData.classIndex, localData.abc, localData.fullyQualifiedNames, methodIndex, (ScopeStack) localData.scopeStack.clone());
stack.push(function);
}

View File

@@ -141,14 +141,5 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S
return 1;
}
@Override
public String getObject(Stack<AVM2Item> stack, ABC abc,
AVM2Instruction ins, List<AVM2Item> output,
MethodBody body, HashMap<Integer, String> localRegNames,
List<DottedChain> fullyQualifiedNames
) {
return AVM2Item.localRegName(localRegNames, getRegisterId(ins));
}
public abstract int getRegisterId(AVM2Instruction ins);
}

View File

@@ -22,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2ConstantPool;
import com.jpexs.decompiler.flash.abc.avm2.LocalDataArea;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import java.util.List;
@@ -43,7 +44,9 @@ public class GetGlobalScopeIns extends InstructionDefinition {
@Override
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, String path) {
stack.push(localData.scopeStack.get(0));
//Note: it is not true that "The global scope object is the object at the bottom of the scope stack.",
//It is special scope which is not present at standard scope stack.
stack.push(new GlobalAVM2Item(ins, localData.lineStartInstruction));
}
@Override

View File

@@ -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.instructions.other;
import com.jpexs.decompiler.flash.abc.ABC;
@@ -21,6 +22,7 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.model.GetSlotAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.Multiname;
@@ -28,6 +30,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.Trait;
import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.helpers.Reference;
import java.util.List;
/**
@@ -43,23 +46,9 @@ public class GetGlobalSlotIns extends InstructionDefinition {
@Override
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, String path) {
int slotIndex = ins.operands[0];
int slotIndex = ins.operands[0];
GraphTargetItem obj = localData.scopeStack.get(0); //scope
Multiname slotname = null;
if (obj instanceof ExceptionAVM2Item) {
slotname = localData.getConstants().getMultiname(((ExceptionAVM2Item) obj).exception.name_index);
} else {
MethodBody body = localData.methodBody;
List<Trait> traits = body.traits.traits;
for (int t = 0; t < traits.size(); t++) {
Trait trait = traits.get(t);
if (trait instanceof TraitSlotConst) {
if (((TraitSlotConst) trait).slot_id == slotIndex) {
slotname = trait.getName(localData.abc);
}
}
}
GraphTargetItem obj = new GlobalAVM2Item(ins, localData.lineStartInstruction);
Reference<GraphTargetItem> realObj = new Reference<>(null);
Multiname slotname = InstructionDefinition.searchSlotName(slotIndex, localData, obj, realObj);
stack.push(new GetSlotAVM2Item(ins, localData.lineStartInstruction, obj, obj, slotIndex, slotname));
}

View File

@@ -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.instructions.other;
import com.jpexs.decompiler.flash.abc.ABC;
@@ -24,6 +25,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.GetSlotAVM2Item;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.helpers.Reference;
import java.util.List;
/**
@@ -41,7 +43,9 @@ public class GetSlotIns extends InstructionDefinition {
int slotIndex = ins.operands[0];
GraphTargetItem objinreg = stack.pop(); //scope
GraphTargetItem obj = objinreg.getThroughRegister();
GraphTargetItem obj = objinreg.getThroughRegister();
Reference<GraphTargetItem> realObj = new Reference<>(null);
Multiname slotname = InstructionDefinition.searchSlotName(slotIndex, localData, obj, realObj);
obj = realObj.getVal();
stack.push(new GetSlotAVM2Item(ins, localData.lineStartInstruction, obj, objinreg, slotIndex, slotname));
}

View File

@@ -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.instructions.other;
import com.jpexs.decompiler.flash.abc.ABC;
@@ -22,8 +23,10 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.avm2.instructions.SetTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item;
import com.jpexs.decompiler.flash.abc.avm2.model.SetSlotAVM2Item;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.abc.types.Multiname;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
@@ -43,18 +46,14 @@ public class SetGlobalSlotIns extends InstructionDefinition implements SetTypeIn
@Override
public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, String path) {
int slotIndex = ins.operands[0];
GraphTargetItem value = stack.pop();
GraphTargetItem value = stack.pop();
GraphTargetItem result = new SetGlobalSlotAVM2Item(ins, localData.lineStartInstruction, ins.operands[0], value);
GraphTargetItem obj = new GlobalAVM2Item(ins, localData.lineStartInstruction);
SetSlotIns.handleSetSlot(localData, stack, ins, output, slotIndex, obj, value);
}
@Override
public int getStackPopCount(AVM2Instruction ins, ABC abc) {
return 1;
}
}
@Override
public String getObject(Stack<AVM2Item> stack, ABC abc, AVM2Instruction ins, List<AVM2Item> output, MethodBody body, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames) {
return "globalslot" + ins.operands[0];
}

View File

@@ -279,15 +279,4 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns
int multinameIndex = ins.operands[0];
return 2 + getMultinameRequiredStackSize(abc.constants, multinameIndex);
}
@Override
public String getObject(Stack<AVM2Item> stack, ABC abc, AVM2Instruction ins, List<AVM2Item> output, MethodBody body, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames) {
int multinameIndex = ins.operands[0];
String multiname = resolveMultinameNoPop(0, stack, abc.constants, multinameIndex, ins, fullyQualifiedNames);
GraphTargetItem obj = stack.get(1 + resolvedCount(abc.constants, multinameIndex)); //pod vrcholem
if ((!obj.toString().isEmpty())) {
multiname = "." + multiname;
}
return obj + multiname;
}
}

View File

@@ -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.instructions.other;
import com.jpexs.decompiler.flash.abc.ABC;
@@ -38,6 +39,7 @@ import com.jpexs.decompiler.flash.abc.types.traits.TraitSlotConst;
import com.jpexs.decompiler.graph.DottedChain;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.helpers.Reference;
import java.util.HashMap;
import java.util.List;
import java.util.Stack;
@@ -57,12 +59,21 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns {
int slotIndex = ins.operands[0];
GraphTargetItem value = stack.pop();
GraphTargetItem obj = stack.pop(); //scopeId
if (obj.getThroughRegister() instanceof NewActivationAVM2Item) {
((NewActivationAVM2Item) obj.getThroughRegister()).slots.put(slotIndex, value);
}
handleSetSlot(localData, stack, ins, output, slotIndex, obj, value);
}
public static void handleSetSlot(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List<GraphTargetItem> output, int slotIndex, GraphTargetItem obj, GraphTargetItem value) {
GraphTargetItem objnoreg = obj;
obj = obj.getThroughRegister();
obj = obj.getThroughRegister();
if (obj instanceof NewActivationAVM2Item) {
((NewActivationAVM2Item) obj).slots.put(slotIndex, value);
}
Reference<GraphTargetItem> realObj = new Reference<>(null);
Multiname slotname = InstructionDefinition.searchSlotName(slotIndex, localData, obj, realObj);
obj = realObj.getVal();
if (slotname != null) {
if (value instanceof LocalRegAVM2Item) {
@@ -134,20 +145,4 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns {
public int getStackPopCount(AVM2Instruction ins, ABC abc) {
return 2;
}
}
@Override
public String getObject(Stack<AVM2Item> stack, ABC abc, AVM2Instruction ins, List<AVM2Item> output, MethodBody body, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames) {
int slotIndex = ins.operands[0];
////String obj = stack.get(1);
String slotname = "";
for (int t = 0; t < body.traits.traits.size(); t++) {
if (body.traits.traits.get(t) instanceof TraitSlotConst) {
if (((TraitSlotConst) body.traits.traits.get(t)).slot_id == slotIndex) {
slotname = body.traits.traits.get(t).getName(abc).getName(abc.constants, fullyQualifiedNames, true, true);
}
}
}
return slotname;
}

View File

@@ -64,13 +64,4 @@ public class SetSuperIns extends InstructionDefinition implements SetTypeIns {
return 2 + getMultinameRequiredStackSize(abc.constants, multinameIndex);
}
@Override
public String getObject(Stack<AVM2Item> stack, ABC abc, AVM2Instruction ins, List<AVM2Item> output, MethodBody body, HashMap<Integer, String> localRegNames, List<DottedChain> fullyQualifiedNames) throws InterruptedException {
int multinameIndex = ins.operands[0];
String multiname = resolveMultinameNoPop(1, stack, abc.constants, multinameIndex, ins, fullyQualifiedNames);
HighlightedTextWriter writer = new HighlightedTextWriter(Configuration.getCodeFormatting(), false);
stack.get(1 + resolvedCount(abc.constants, multinameIndex)).toString(writer, LocalData.create(abc, localRegNames, fullyQualifiedNames));
String obj = writer.toString();
return obj + ".super." + multiname;
}
}

View File

@@ -12,56 +12,51 @@
* 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;
import com.jpexs.decompiler.flash.ecma.ObjectType;
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
import com.jpexs.decompiler.graph.GraphPart;
import com.jpexs.decompiler.graph.GraphSourceItem;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TypeItem;
import com.jpexs.decompiler.graph.model.LocalData;
import java.util.HashMap;
/**
*
* @author JPEXS
*/
public class SetGlobalSlotAVM2Item extends AVM2Item {
public class GlobalAVM2Item extends AVM2Item {
public int slotId;
@Override
public GraphPart getFirstPart() {
return value.getFirstPart();
}
public SetGlobalSlotAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns, int slotId, GraphTargetItem value) {
super(instruction, lineStartIns, PRECEDENCE_ASSIGMENT, value);
this.slotId = slotId;
public GlobalAVM2Item(GraphSourceItem instruction, GraphSourceItem lineStartIns) {
super(instruction, lineStartIns, PRECEDENCE_PRIMARY);
}
@Override
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
writer.append("§§setglobalslot");
writer.spaceBeforeCallParenthesies(2);
writer.append("(");
writer.append(slotId).append(",");
value.toString(writer, localData);
return writer.append(")");
return writer.append("global");
}
@Override
public boolean hasSideEffect() {
public Object getResult() {
return new ObjectType(new HashMap<>()) {
@Override
public String toString() {
return "global";
}
};
}
@Override
public boolean hasReturnValue() {
return true;
}
@Override
public GraphTargetItem returnType() {
return TypeItem.UNBOUNDED;
return new TypeItem("global");
}
@Override
public boolean hasReturnValue() {
return false;
}
}

View File

@@ -87,7 +87,7 @@ public class NewFunctionAVM2Item extends AVM2Item {
abc.method_info.get(methodIndex).getReturnTypeStr(writer, abc.constants, fullyQualifiedNames);
writer.startBlock();
if (body != null) {
body.convert(new ConvertData(), path + "/inner", ScriptExportMode.AS, isStatic, methodIndex, scriptIndex, classIndex, abc, null, (ScopeStack) this.scopeStack.clone(), 0, new NulWriter(), fullyQualifiedNames, null, false);
body.convert(new ConvertData(), path + "/inner", ScriptExportMode.AS, isStatic, methodIndex, scriptIndex, classIndex, abc, null, new ScopeStack(), 0, new NulWriter(), fullyQualifiedNames, null, false);
body.toString(path + "/inner", ScriptExportMode.AS, abc, null, writer, fullyQualifiedNames);
}
writer.endBlock();

View File

@@ -93,7 +93,7 @@ public abstract class ActionScript3DecompileTestBase extends ActionScriptTestBas
Configuration.autoDeobfuscate.set(methodName.toLowerCase().contains("obfus"));
abc.bodies.get(bodyIndex).convert(new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(scriptIndex), 0, new NulWriter(), new ArrayList<>(), ts, true);
abc.bodies.get(bodyIndex).convert(new ConvertData(), "run", ScriptExportMode.AS, isStatic, abc.bodies.get(bodyIndex).method_info, scriptIndex, clsIndex, abc, null, new ScopeStack(), 0, new NulWriter(), new ArrayList<>(), ts, true);
writer = new HighlightedTextWriter(new CodeFormatting(), false);
abc.bodies.get(bodyIndex).toString("run", ScriptExportMode.AS, abc, null, writer, new ArrayList<>());
} catch (InterruptedException ex) {

View File

@@ -26,14 +26,15 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
@BeforeClass
public void init() throws IOException, InterruptedException {
addSwf("standard", "testdata/as3_new/bin/as3_new.flex.swf");
addSwf("assembled", "testdata/as3_assembled/bin/as3_assembled.swf");
}
private void decompileScriptPack(String path, String expectedResult) {
private void decompileScriptPack(String swfId, String path, String expectedResult) {
DoABC2Tag tag = null;
ABC abc = null;
ScriptPack scriptPack = null;
for (Tag t : getSwf("standard").getTags()) {
for (Tag t : getSwf(swfId).getTags()) {
if (t instanceof DoABC2Tag) {
tag = (DoABC2Tag) t;
abc = tag.getABC();
@@ -59,7 +60,7 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
@Test
public void testMyPackage1TestClass() {
decompileScriptPack("tests_classes.mypackage1.TestClass", "package tests_classes.mypackage1\n"
decompileScriptPack("standard", "tests_classes.mypackage1.TestClass", "package tests_classes.mypackage1\n"
+ "{\n"
+ " public class TestClass implements tests_classes.mypackage1.TestInterface\n"
+ " {\n"
@@ -96,7 +97,7 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
@Test
public void testMyPackage1TestClass2() {
decompileScriptPack("tests_classes.mypackage1.TestClass2", "package tests_classes.mypackage1\n"
decompileScriptPack("standard", "tests_classes.mypackage1.TestClass2", "package tests_classes.mypackage1\n"
+ "{\n"
+ " public class TestClass2\n"
+ " {\n"
@@ -139,7 +140,7 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
@Test
public void testMyPackage1TestInterface() {
decompileScriptPack("tests_classes.mypackage1.TestInterface", "package tests_classes.mypackage1\n"
decompileScriptPack("standard", "tests_classes.mypackage1.TestInterface", "package tests_classes.mypackage1\n"
+ "{\n"
+ " public interface TestInterface extends tests_classes.mypackage2.TestInterface\n"
+ " {\n"
@@ -151,7 +152,7 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
@Test
public void testMyPackage1MyNamespace() {
decompileScriptPack("tests_classes.mypackage1.myNamespace", "package tests_classes.mypackage1\n"
decompileScriptPack("standard", "tests_classes.mypackage1.myNamespace", "package tests_classes.mypackage1\n"
+ "{\n"
+ " public namespace myNamespace = \"https://www.free-decompiler.com/flash/test/namespace\";\n"
+ "}");
@@ -159,7 +160,7 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
@Test
public void testMyPackage2TestClass() {
decompileScriptPack("tests_classes.mypackage2.TestClass", "package tests_classes.mypackage2\n"
decompileScriptPack("standard", "tests_classes.mypackage2.TestClass", "package tests_classes.mypackage2\n"
+ "{\n"
+ " public class TestClass implements TestInterface\n"
+ " {\n"
@@ -184,7 +185,7 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
@Test
public void testMyPackage2TestInterface() {
decompileScriptPack("tests_classes.mypackage2.TestInterface", "package tests_classes.mypackage2\n"
decompileScriptPack("standard", "tests_classes.mypackage2.TestInterface", "package tests_classes.mypackage2\n"
+ "{\n"
+ " public interface TestInterface\n"
+ " {\n"
@@ -196,7 +197,7 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
@Test
public void testMyPackage3TestClass() {
decompileScriptPack("tests_classes.mypackage3.TestClass", "package tests_classes.mypackage3\n"
decompileScriptPack("standard", "tests_classes.mypackage3.TestClass", "package tests_classes.mypackage3\n"
+ "{\n"
+ " public class TestClass\n"
+ " {\n"
@@ -217,7 +218,7 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
@Test
public void testThisOutsideClass() {
decompileScriptPack("tests_classes.TestThisOutsideClass", "package tests_classes\n"
decompileScriptPack("standard", "tests_classes.TestThisOutsideClass", "package tests_classes\n"
+ "{\n"
+ " public class TestThisOutsideClass\n"
+ " {\n"
@@ -243,4 +244,54 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
+ " this.attrib++;\n"
+ "}");
}
@Test
public void testSlots() {
decompileScriptPack("assembled", "tests.TestSlots", "package tests\n"
+ "{\n"
+ " public class TestSlots\n"
+ " {\n"
+ " \n"
+ " public static var classVar1:String = \"cls1\";\n"
+ " \n"
+ " public static var classVar2:String = \"cls2\";\n"
+ " \n"
+ " \n"
+ " public var instanceVar1:String = \"ins1\";\n"
+ " \n"
+ " public var instanceVar2:String = \"ins2\";\n"
+ " \n"
+ " public function TestSlots()\n"
+ " {\n"
+ " super();\n"
+ " }\n"
+ " \n"
+ " public static function classMethod() : void\n"
+ " {\n"
+ " trace(classVar1);\n"
+ " trace(classVar2);\n"
+ " trace(globalVar1);\n"
+ " trace(globalVar2);\n"
+ " }\n"
+ " \n"
+ " public function instanceMethod() : void\n"
+ " {\n"
+ " trace(instanceVar1);\n"
+ " trace(instanceVar2);\n"
+ " trace(globalVar1);\n"
+ " trace(globalVar2);\n"
+ " }\n"
+ " }\n"
+ "}\n"
+ "\n"
+ "var globalVar1:String = \"glb1\";\n"
+ "\n"
+ "var globalVar2:String = \"glb2\";\n"
+ "\n"
+ "function globalFunction():void\n"
+ "{\n"
+ " trace(globalVar1);\n"
+ " trace(globalVar2);\n"
+ "}");
}
}

View File

@@ -880,6 +880,18 @@ public class ActionScript3ClassicAirDecompileTest extends ActionScript3Decompile
false);
}
@Test
public void testInnerFunctionScope() {
decompileMethod("classic_air", "testInnerFunctionScope", "a = a;\r\n"
+ "var innerFunc:Function = function(b:String):*\r\n"
+ "{\r\n"
+ "testProm = 4;\r\n"
+ "trace(testProm);\r\n"
+ "};\r\n"
+ "innerFunc(a);\r\n",
false);
}
@Test
public void testInnerFunctions() {
decompileMethod("classic_air", "testInnerFunctions", "a = a;\r\n"

View File

@@ -874,6 +874,17 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes
false);
}
@Test
public void testInnerFunctionScope() {
decompileMethod("classic", "testInnerFunctionScope", "var innerFunc:Function = function(b:String):*\r\n"
+ "{\r\n"
+ "testProm = 4;\r\n"
+ "trace(testProm);\r\n"
+ "};\r\n"
+ "innerFunc(a);\r\n",
false);
}
@Test
public void testInnerFunctions() {
decompileMethod("classic", "testInnerFunctions", "var s:int = 0;\r\n"

View File

@@ -417,15 +417,16 @@ public class ActionScript3CrossCompileDecompileTest extends ActionScript3Decompi
+ "trace(\"in catch1\");\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "trace(\"xx\");\r\n"
+ "if(a > 5)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"yy\");\r\n"
+ "}\r\n"
+ "trace(\"in catch1c\");\r\n"
+ "}\r\n"
+ "}\r\n"
+ "trace(\"after\");\r\n",
+ "}\r\n",
false);
}

View File

@@ -408,15 +408,16 @@ public class ActionScript3CrossCompileSwfToolsDecompileTest extends ActionScript
+ "trace(\"in catch1\");\r\n"
+ "while(true)\r\n"
+ "{\r\n"
+ "trace(\"xx\");\r\n"
+ "if(_loc1_ > 5)\r\n"
+ "{\r\n"
+ "break;\r\n"
+ "}\r\n"
+ "trace(\"yy\");\r\n"
+ "}\r\n"
+ "trace(\"in catch1c\");\r\n"
+ "}\r\n"
+ "}\r\n"
+ "trace(\"after\");\r\n",
+ "}\r\n",
false);
}

View File

@@ -23,5 +23,7 @@ program
#include "tests/TestDeobfuscatorJumpsExceptionStart.script.asasm"
#include "tests/TestUnnamedException.script.asasm"
#include "tests/TestTryCatchLoopBreakLevel2.script.asasm"
#include "tests/TestSlots.script.asasm"
#include "tests/TestSlots.init/inline_method.method.asasm"
; place to add next
end ; program

View File

@@ -0,0 +1,163 @@
class
refid "tests:TestSlots"
instance QName(PackageNamespace("tests"), "TestSlots")
extends QName(PackageNamespace(""), "Object")
flag SEALED
iinit
refid "tests:TestSlots/instance/init"
body
maxstack 1
localcount 1
initscopedepth 0
maxscopedepth 1
code
getlocal0
pushscope
getlocal0
constructsuper 0
returnvoid
end ; code
end ; body
end ; method
trait slot QName(PackageNamespace(""), "instanceVar1") flag METADATA type QName(PackageNamespace(""), "String") value Utf8("ins1")
slotid 1
metadata "__go_to_definition_help"
item "pos" "106"
end ; metadata
end ; trait
trait slot QName(PackageNamespace(""), "instanceVar2") flag METADATA type QName(PackageNamespace(""), "String") value Utf8("ins2")
slotid 2
metadata "__go_to_definition_help"
item "pos" "150"
end ; metadata
end ; trait
trait method QName(PackageNamespace(""), "instanceMethod") flag METADATA
method
name "instanceMethod"
refid "tests:TestSlots/instance/instanceMethod"
returns QName(PackageNamespace(""), "void")
body
maxstack 3
localcount 1
initscopedepth 0
maxscopedepth 1
code
getlocal0
pushscope
debugfile "C:\\Dropbox\\Programovani\\JavaSE\\FFDec\\libsrc\\ffdec_lib\\testdata\\testslots\\src;tests;TestSlots.as"
findpropstrict QName(PackageNamespace(""), "trace")
debugline 18
getscopeobject 0
getslot 1 ;instanceVar1
callpropvoid QName(PackageNamespace(""), "trace"), 1
findpropstrict QName(PackageNamespace(""), "trace")
debugline 19
getscopeobject 0
getslot 2 ;instanceVar2
callpropvoid QName(PackageNamespace(""), "trace"), 1
;these are nested, I think this won't happen in real files
;findpropstrict QName(PackageNamespace(""), "trace")
;debugline 20
;getglobalscope
;getslot 3 ;TestSlots
;getslot 1 ;classVar1
;callpropvoid QName(PackageNamespace(""), "trace"), 1
;findpropstrict QName(PackageNamespace(""), "trace")
;debugline 21
;getglobalscope
;getslot 3 ;TestSlots
;getslot 2 ;classVar2
;callpropvoid QName(PackageNamespace(""), "trace"), 1
findpropstrict QName(PackageNamespace(""), "trace")
debugline 22
getglobalscope
getslot 1 ;globalVar1
callpropvoid QName(PackageNamespace(""), "trace"), 1
findpropstrict QName(PackageNamespace(""), "trace")
debugline 23
getglobalscope
getslot 2 ;globalVar2
callpropvoid QName(PackageNamespace(""), "trace"), 1
returnvoid
end ; code
end ; body
end ; method
metadata "__go_to_definition_help"
item "pos" "309"
end ; metadata
end ; trait
end ; instance
cinit
refid "tests:TestSlots/class/init"
body
maxstack 0
localcount 1
initscopedepth 0
maxscopedepth 0
code
returnvoid
end ; code
end ; body
end ; method
trait slot QName(PackageNamespace(""), "classVar1") flag METADATA type QName(PackageNamespace(""), "String") value Utf8("cls1")
slotid 1
metadata "__go_to_definition_help"
item "pos" "205"
end ; metadata
end ; trait
trait slot QName(PackageNamespace(""), "classVar2") flag METADATA type QName(PackageNamespace(""), "String") value Utf8("cls2")
slotid 2
metadata "__go_to_definition_help"
item "pos" "254"
end ; metadata
end ; trait
trait method QName(PackageNamespace(""), "classMethod") flag METADATA
method
name "classMethod"
refid "tests:TestSlots/class/classMethod"
returns QName(PackageNamespace(""), "void")
body
maxstack 3
localcount 1
initscopedepth 0
maxscopedepth 1
code
getlocal0
pushscope
debugfile "C:\\Dropbox\\Programovani\\JavaSE\\FFDec\\libsrc\\ffdec_lib\\testdata\\testslots\\src;tests;TestSlots.as"
findpropstrict QName(PackageNamespace(""), "trace")
debugline 28
getscopeobject 0
getslot 1 ;classVar1
callpropvoid QName(PackageNamespace(""), "trace"), 1
findpropstrict QName(PackageNamespace(""), "trace")
debugline 29
getscopeobject 0
getslot 2 ;classVar2
callpropvoid QName(PackageNamespace(""), "trace"), 1
findpropstrict QName(PackageNamespace(""), "trace")
debugline 30
getglobalscope
getslot 1 ;globalVar1
callpropvoid QName(PackageNamespace(""), "trace"), 1
findpropstrict QName(PackageNamespace(""), "trace")
debugline 31
getglobalscope
getslot 2 ;globalVar2
callpropvoid QName(PackageNamespace(""), "trace"), 1
returnvoid
end ; code
end ; body
end ; method
metadata "__go_to_definition_help"
item "pos" "512"
end ; metadata
end ; trait
end ; class

View File

@@ -0,0 +1,29 @@
method
name "globalFunction"
refid "tests:TestSlots/init/inline_method"
returns QName(PackageNamespace(""), "void")
body
maxstack 3
localcount 1
initscopedepth 0
maxscopedepth 1
code
getlocal0
pushscope
debugfile "C:\\Dropbox\\Programovani\\JavaSE\\FFDec\\libsrc\\ffdec_lib\\testdata\\testslots\\src;tests;TestSlots.as"
getlex QName(PackageNamespace(""), "trace")
debugline 43
getglobalscope
getlex QName(PrivateNamespace("FilePrivateNS:TestSlots"), "globalVar1")
call 1
pop
getlex QName(PackageNamespace(""), "trace")
debugline 44
getglobalscope
getlex QName(PrivateNamespace("FilePrivateNS:TestSlots"), "globalVar2")
call 1
returnvoid
end ; code
end ; body
end ; method

View File

@@ -0,0 +1,57 @@
script
sinit
refid "tests:TestSlots/init"
body
maxstack 3
localcount 1
initscopedepth 0
maxscopedepth 2
code
getlocal0
pushscope
getscopeobject 0
getlex QName(PackageNamespace(""), "Object")
dup
pushscope
newclass "tests:TestSlots"
popscope
initproperty QName(PackageNamespace("tests"), "TestSlots")
getglobalscope
newfunction "tests:TestSlots/init/inline_method"
setproperty QName(PrivateNamespace("FilePrivateNS:TestSlots"), "globalFunction")
debugfile "C:\\Dropbox\\Programovani\\JavaSE\\FFDec\\libsrc\\ffdec_lib\\testdata\\testslots\\src;tests;TestSlots.as"
debugline 38
pushstring "glb1"
findproperty QName(PrivateNamespace("FilePrivateNS:TestSlots"), "globalVar1")
swap
setproperty QName(PrivateNamespace("FilePrivateNS:TestSlots"), "globalVar1")
debugline 39
pushstring "glb2"
findproperty QName(PrivateNamespace("FilePrivateNS:TestSlots"), "globalVar2")
swap
setproperty QName(PrivateNamespace("FilePrivateNS:TestSlots"), "globalVar2")
returnvoid
end ; code
end ; body
end ; method
trait class QName(PackageNamespace("tests"), "TestSlots") flag METADATA
slotid 3
#include "TestSlots.class.asasm"
metadata "__go_to_definition_help"
item "pos" "73"
end ; metadata
end ; trait
trait slot QName(PrivateNamespace("FilePrivateNS:TestSlots"), "globalVar1") type QName(PackageNamespace(""), "String")
slotid 1
end
trait slot QName(PrivateNamespace("FilePrivateNS:TestSlots"), "globalVar2") type QName(PackageNamespace(""), "String")
slotid 2
end
trait slot QName(PrivateNamespace("FilePrivateNS:TestSlots"), "globalFunction") end
end ; script

View File

@@ -3,6 +3,8 @@
<!--Any modifications you make may be lost.-->
<flex-config>
<target-player>25.0</target-player>
<benchmark>false</benchmark>
<static-link-runtime-shared-libraries>true</static-link-runtime-shared-libraries>
<compiler>
<define append="true">
<name>CONFIG::debug</name>

View File

@@ -23,14 +23,16 @@ package tests
{
trace("in catch1");
while (true){
trace("xx");
if (a > 5){
break;
}
trace("yy");
}
trace("in catch1c");
}
}
trace("after");
//trace("after");
}