From e69d4929534680d5e4d68b17e5104e694eb62959 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sun, 15 Jan 2023 23:05:32 +0100 Subject: [PATCH] Fixed #1938 AS3 - shortening + 1 to increment Fixed #1938 AS3 - implicit coercion of operations Fixed #1938 AS3 - initproperty compound operators, increment/decrement --- CHANGELOG.md | 3 + .../instructions/InstructionDefinition.java | 315 ++++++++++++++++++ .../instructions/other/InitPropertyIns.java | 31 +- .../instructions/other/SetPropertyIns.java | 309 +---------------- .../avm2/model/operations/AddAVM2Item.java | 4 +- .../avm2/model/operations/NegAVM2Item.java | 2 +- .../model/operations/SubtractAVM2Item.java | 4 +- .../decompiler/graph/model/BinaryOpItem.java | 8 +- .../decompiler/graph/model/UnaryOpItem.java | 4 +- .../ActionScript3ClassicDecompileTest.java | 4 +- 10 files changed, 335 insertions(+), 349 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d763ef7e3..81fa7d920 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,9 @@ All notable changes to this project will be documented in this file. - [#1938] AS3 Direct editation - setting default values for slots - AS3 Direct editation - using local classes as types - [#1938] AS3 - coercion call type +- [#1938] AS3 - shortening + 1 to increment +- [#1938] AS3 - implicit coercion of operations +- [#1938] AS3 - initproperty compound operators, increment/decrement ## [18.3.2] - 2023-01-10 ### Removed diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java index 20305be06..20c4e5ad9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/InstructionDefinition.java @@ -28,14 +28,33 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.DecLocalIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.IncLocalIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.localregs.SetLocalTypeIns; +import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns; +import static com.jpexs.decompiler.flash.abc.avm2.instructions.other.SetPropertyIns.handleCompound; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.ApplyTypeAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ClassAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.ConstructAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.DecrementAVM2Item; 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.GetLexAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.GetPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.GlobalAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.IncrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.InitPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item; +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.PostDecrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.PostIncrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetTypeAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ThisAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreDecrementAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.operations.PreIncrementAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.abc.types.Multiname; @@ -49,6 +68,7 @@ import com.jpexs.decompiler.graph.GraphSourceItem; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.ScopeStack; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.DuplicateItem; import com.jpexs.helpers.Reference; import java.io.Serializable; import java.util.ArrayList; @@ -56,6 +76,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.Stack; @@ -380,4 +401,298 @@ public abstract class InstructionDefinition implements Serializable { return null; } + + public void handleSetProperty(boolean init, AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { + int multinameIndex = ins.operands[0]; + GraphTargetItem value = stack.pop(); + FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); + GraphTargetItem obj = stack.pop(); + //assembled/TestIncrement + if ((value instanceof IncrementAVM2Item) || (value instanceof DecrementAVM2Item)) { + boolean isIncrement = (value instanceof IncrementAVM2Item); + if (value.value instanceof DuplicateItem) { + GraphTargetItem duplicated = value.value.value; + if (!stack.isEmpty()) { + if (stack.peek() == duplicated) { + GraphTargetItem notCoerced = duplicated.getNotCoerced(); + if (notCoerced instanceof GetLexAVM2Item) { + GetLexAVM2Item getLex = (GetLexAVM2Item) notCoerced; + if (localData.abc.constants.getMultiname(multinameIndex).equals(getLex.propertyName) + && (obj instanceof FindPropertyAVM2Item)) { + stack.pop(); + if (isIncrement) { + stack.push(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getLex)); + } else { + stack.push(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getLex)); + } + return; + } + } + if (notCoerced instanceof GetPropertyAVM2Item) { + GetPropertyAVM2Item getProp = (GetPropertyAVM2Item) notCoerced; + if (((FullMultinameAVM2Item) getProp.propertyName).compareSame(multiname)) { + + if (getProp.object instanceof DuplicateItem) { //assembled/TestIncrement3 + if (getProp.object.value == obj) { + getProp.object = obj; + } + } + + if (Objects.equals(obj, getProp.object)) { + stack.pop(); + if (isIncrement) { + stack.push(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getProp)); + } else { + stack.push(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getProp)); + } + return; + } + } + } + } + } + } + } + + if ((value instanceof IncrementAVM2Item) || (value instanceof DecrementAVM2Item)) { + boolean isIncrement = (value instanceof IncrementAVM2Item); + + boolean hasConvert = value.value instanceof ConvertAVM2Item; + if (value.value.getNotCoercedNoDup() instanceof GetLexAVM2Item) { + GetLexAVM2Item getLex = (GetLexAVM2Item) value.value.getNotCoercedNoDup(); + if (localData.abc.constants.getMultiname(multinameIndex).equals(getLex.propertyName) + && (obj instanceof FindPropertyAVM2Item)) { + if (hasConvert) { + if (isIncrement) { + output.add(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getLex)); + } else { + output.add(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getLex)); + } + } else { + if (isIncrement) { + output.add(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getLex)); + } else { + output.add(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getLex)); + } + } + return; + } + } + + if (value.value.getNotCoercedNoDup() instanceof GetPropertyAVM2Item) { + GetPropertyAVM2Item getProp = (GetPropertyAVM2Item) value.value.getNotCoercedNoDup(); + if (((FullMultinameAVM2Item) getProp.propertyName).compareSame(multiname)) { + + if (getProp.object instanceof DuplicateItem) { + if (getProp.object.value == obj) { + getProp.object = obj; + } + } + if (Objects.equals(getProp.object, obj)) { + if (hasConvert) { + if (isIncrement) { + output.add(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getProp)); + } else { + output.add(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getProp)); + } + } else { + if (isIncrement) { + output.add(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getProp)); + } else { + output.add(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getProp)); + } + } + return; + } + } + } + } + //assembled/TestIncrement2 + if (value instanceof DuplicateItem) { + GraphTargetItem duplicated = value.value; + if ((duplicated instanceof IncrementAVM2Item) || (duplicated instanceof DecrementAVM2Item)) { + boolean isIncrement = (duplicated instanceof IncrementAVM2Item); + if (!stack.isEmpty()) { + if (stack.peek() == duplicated) { + GraphTargetItem incrementedProp = duplicated.value; + if (incrementedProp instanceof GetLexAVM2Item) { + GetLexAVM2Item getLex = (GetLexAVM2Item) incrementedProp; + if (localData.abc.constants.getMultiname(multinameIndex).equals(getLex.propertyName) + && (obj instanceof FindPropertyAVM2Item)) { + stack.pop(); + if (isIncrement) { + stack.push(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getLex)); + } else { + stack.push(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getLex)); + } + return; + } + } + if (incrementedProp instanceof GetPropertyAVM2Item) { + GetPropertyAVM2Item getProp = (GetPropertyAVM2Item) incrementedProp; + if (((FullMultinameAVM2Item) getProp.propertyName).compareSame(multiname) + && (Objects.equals(getProp.object, obj))) { + stack.pop(); + if (isIncrement) { + stack.push(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getProp)); + } else { + stack.push(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getProp)); + } + return; + } + } + } + } + } + } + if (value instanceof LocalRegAVM2Item) { + LocalRegAVM2Item valueLocalReg = (LocalRegAVM2Item) value; + LocalRegAVM2Item nameLocalReg = null; + if (multiname.name instanceof LocalRegAVM2Item) { + nameLocalReg = (LocalRegAVM2Item) multiname.name;; + } + if (obj instanceof LocalRegAVM2Item) { + LocalRegAVM2Item objLocalReg = (LocalRegAVM2Item) obj; + + if (!output.isEmpty()) { + if (output.get(output.size() - 1) instanceof SetLocalAVM2Item) { + SetLocalAVM2Item valueSetLocalReg = (SetLocalAVM2Item) output.get(output.size() - 1); + if ((valueSetLocalReg.value instanceof IncrementAVM2Item) + || (valueSetLocalReg.value instanceof DecrementAVM2Item)) { + boolean isIncrement = (valueSetLocalReg.value instanceof IncrementAVM2Item); + if (valueSetLocalReg.value.value instanceof DuplicateItem) { + GraphTargetItem duplicated = valueSetLocalReg.value.value.value; + if (!stack.isEmpty() && stack.peek() == duplicated) { + GraphTargetItem notCoerced = duplicated.getNotCoerced(); + if (notCoerced instanceof GetPropertyAVM2Item) { + GetPropertyAVM2Item getProperty = (GetPropertyAVM2Item) notCoerced; + FullMultinameAVM2Item propertyName = ((FullMultinameAVM2Item) getProperty.propertyName); + SetLocalAVM2Item nameSetLocalReg = null; + if (propertyName.name instanceof SetLocalAVM2Item) { + nameSetLocalReg = (SetLocalAVM2Item) propertyName.name; + } + if (getProperty.object instanceof SetLocalAVM2Item) { + SetLocalAVM2Item objSetLocalReg = (SetLocalAVM2Item) getProperty.object; + + if ((valueLocalReg.regIndex == valueSetLocalReg.regIndex) + && (propertyName.multinameIndex == multinameIndex) + && ((nameLocalReg == null && nameSetLocalReg == null) || (nameLocalReg.regIndex == nameSetLocalReg.regIndex)) + && (objLocalReg.regIndex == objSetLocalReg.regIndex)) { + if (nameSetLocalReg != null) { + propertyName.name = nameSetLocalReg.value; + } + getProperty.object = objSetLocalReg.value; + output.remove(output.size() - 1); + stack.pop(); + if (isIncrement) { + stack.push(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getProperty)); + } else { + stack.push(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getProperty)); + } + return; + } + } + } + } + } + } + } + } + + if (!stack.isEmpty()) { + GraphTargetItem checked = checkIncDec(false, multinameIndex, ins, localData, stack.peek(), valueLocalReg, nameLocalReg, objLocalReg); + if (checked != null) { + stack.pop(); + stack.push(checked); + return; + } + } + if (!output.isEmpty()) { + GraphTargetItem checked = checkIncDec(true, multinameIndex, ins, localData, output.get(output.size() - 1), valueLocalReg, nameLocalReg, objLocalReg); + if (checked != null) { + output.remove(output.size() - 1); + output.add(checked); + return; + } + } + } + } + + if (obj.getThroughDuplicate() instanceof ConstructAVM2Item) { + ConstructAVM2Item c = (ConstructAVM2Item) obj.getThroughDuplicate(); + if (c.object instanceof ApplyTypeAVM2Item) { + ApplyTypeAVM2Item at = (ApplyTypeAVM2Item) c.object; + c.args.clear(); + List vals = new ArrayList<>(); + vals.add(value); + c.object = new InitVectorAVM2Item(c.getInstruction(), c.getLineStartIns(), at.params.get(0), vals); + return; + } else if (c.object instanceof InitVectorAVM2Item) { + InitVectorAVM2Item iv = (InitVectorAVM2Item) c.object; + iv.arguments.add(value); + return; + } + } + + Reference isStatic = new Reference<>(false); + Reference type = new Reference<>(null); + Reference callType = new Reference<>(null); + GetPropertyIns.resolvePropertyType(localData, obj, multiname, isStatic, type, callType); + + + SetTypeAVM2Item result; + if (init) { + result = new InitPropertyAVM2Item(ins, localData.lineStartInstruction, obj, multiname, value, type.getVal(), callType.getVal(), isStatic.getVal()); + } else { + result = new SetPropertyAVM2Item(ins, localData.lineStartInstruction, obj, multiname, value, type.getVal(), callType.getVal(), isStatic.getVal()); + } + handleCompound(localData, obj, multiname, value, output, result); + SetTypeIns.handleResult(value, stack, output, localData, (GraphTargetItem)result, -1, type.getVal()); + } + + private GraphTargetItem checkIncDec(boolean standalone, int multinameIndex, AVM2Instruction ins, AVM2LocalData localData, GraphTargetItem item, + LocalRegAVM2Item valueLocalReg, LocalRegAVM2Item nameLocalReg, LocalRegAVM2Item objLocalReg) { + if (item instanceof SetLocalAVM2Item) { + SetLocalAVM2Item valueSetLocalReg = (SetLocalAVM2Item) item; + if ((valueSetLocalReg.value instanceof IncrementAVM2Item) || (valueSetLocalReg.value instanceof DecrementAVM2Item)) { + boolean isIncrement = (valueSetLocalReg.value instanceof IncrementAVM2Item); + boolean hasConvert = valueSetLocalReg.value.value instanceof ConvertAVM2Item; //in air there is convert added when postincrement + + if (valueSetLocalReg.value.value.getNotCoercedNoDup() instanceof GetPropertyAVM2Item) { + GetPropertyAVM2Item getProperty = (GetPropertyAVM2Item) valueSetLocalReg.value.value.getNotCoercedNoDup(); + FullMultinameAVM2Item propertyName = ((FullMultinameAVM2Item) getProperty.propertyName); + SetLocalAVM2Item nameSetLocalReg = null; + if (propertyName.name instanceof SetLocalAVM2Item) { + nameSetLocalReg = (SetLocalAVM2Item) propertyName.name; + } + if (getProperty.object instanceof SetLocalAVM2Item) { + SetLocalAVM2Item objSetLocalReg = (SetLocalAVM2Item) getProperty.object; + + if ((valueLocalReg.regIndex == valueSetLocalReg.regIndex) + && (propertyName.multinameIndex == multinameIndex) + && ((nameLocalReg == null && nameSetLocalReg == null) || (nameLocalReg.regIndex == nameSetLocalReg.regIndex)) + && (objLocalReg.regIndex == objSetLocalReg.regIndex)) { + if (nameSetLocalReg != null) { + propertyName.name = nameSetLocalReg.value; + } + getProperty.object = objSetLocalReg.value; + + if (isIncrement) { + if (hasConvert && standalone) { + return new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getProperty); + } + return new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getProperty); + } else { + if (hasConvert && standalone) { + return new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getProperty); + } + return new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getProperty); + } + } + } + } + } + } + return null; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/InitPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/InitPropertyIns.java index d66179804..e9365ed31 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/InitPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/InitPropertyIns.java @@ -40,36 +40,7 @@ public class InitPropertyIns extends InstructionDefinition { @Override public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { - int multinameIndex = ins.operands[0]; - - GraphTargetItem val = stack.pop(); - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); - GraphTargetItem obj = stack.pop(); - - /*GraphTargetItem propertyType = TypeItem.UNBOUNDED; - String multinameStr = localData.abc.constants.getMultiname(multiname.multinameIndex).getName(localData.abc.constants, new ArrayList<>(), true, true); - - for (Trait t : localData.methodBody.traits.traits) { - if (t instanceof TraitSlotConst) { - TraitSlotConst tsc = (TraitSlotConst) t; - if (Objects.equals( - tsc.getName(localData.abc).getName(localData.abc.constants, new ArrayList<>(), true, true), - multinameStr - )) { - propertyType = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); - break; - } - } - }*/ - - Reference isStatic = new Reference<>(false); - Reference type = new Reference<>(null); - Reference callType = new Reference<>(null); - GetPropertyIns.resolvePropertyType(localData, obj, multiname, isStatic, type, callType); - - InitPropertyAVM2Item result = new InitPropertyAVM2Item(ins, localData.lineStartInstruction, obj, multiname, val, type.getVal(), callType.getVal(), isStatic.getVal()); - SetPropertyIns.handleCompound(localData, obj, multiname, val, output, result); - output.add(result); + handleSetProperty(true, localData, stack, ins, output, path); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java index 93ef4f17e..41bb93f00 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetPropertyIns.java @@ -58,313 +58,10 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns public SetPropertyIns() { super(0x61, "setproperty", new int[]{AVM2Code.DAT_MULTINAME_INDEX}, true); } - - private GraphTargetItem checkIncDec(boolean standalone, int multinameIndex, AVM2Instruction ins, AVM2LocalData localData, GraphTargetItem item, - LocalRegAVM2Item valueLocalReg, LocalRegAVM2Item nameLocalReg, LocalRegAVM2Item objLocalReg) { - if (item instanceof SetLocalAVM2Item) { - SetLocalAVM2Item valueSetLocalReg = (SetLocalAVM2Item) item; - if ((valueSetLocalReg.value instanceof IncrementAVM2Item) || (valueSetLocalReg.value instanceof DecrementAVM2Item)) { - boolean isIncrement = (valueSetLocalReg.value instanceof IncrementAVM2Item); - boolean hasConvert = valueSetLocalReg.value.value instanceof ConvertAVM2Item; //in air there is convert added when postincrement - - if (valueSetLocalReg.value.value.getNotCoercedNoDup() instanceof GetPropertyAVM2Item) { - GetPropertyAVM2Item getProperty = (GetPropertyAVM2Item) valueSetLocalReg.value.value.getNotCoercedNoDup(); - FullMultinameAVM2Item propertyName = ((FullMultinameAVM2Item) getProperty.propertyName); - SetLocalAVM2Item nameSetLocalReg = null; - if (propertyName.name instanceof SetLocalAVM2Item) { - nameSetLocalReg = (SetLocalAVM2Item) propertyName.name; - } - if (getProperty.object instanceof SetLocalAVM2Item) { - SetLocalAVM2Item objSetLocalReg = (SetLocalAVM2Item) getProperty.object; - - if ((valueLocalReg.regIndex == valueSetLocalReg.regIndex) - && (propertyName.multinameIndex == multinameIndex) - && ((nameLocalReg == null && nameSetLocalReg == null) || (nameLocalReg.regIndex == nameSetLocalReg.regIndex)) - && (objLocalReg.regIndex == objSetLocalReg.regIndex)) { - if (nameSetLocalReg != null) { - propertyName.name = nameSetLocalReg.value; - } - getProperty.object = objSetLocalReg.value; - - if (isIncrement) { - if (hasConvert && standalone) { - return new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getProperty); - } - return new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getProperty); - } else { - if (hasConvert && standalone) { - return new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getProperty); - } - return new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getProperty); - } - } - } - } - } - } - return null; - } - + @Override - public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { - int multinameIndex = ins.operands[0]; - GraphTargetItem value = stack.pop(); - FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); - GraphTargetItem obj = stack.pop(); - - //assembled/TestIncrement - if ((value instanceof IncrementAVM2Item) || (value instanceof DecrementAVM2Item)) { - boolean isIncrement = (value instanceof IncrementAVM2Item); - if (value.value instanceof DuplicateItem) { - GraphTargetItem duplicated = value.value.value; - if (!stack.isEmpty()) { - if (stack.peek() == duplicated) { - GraphTargetItem notCoerced = duplicated.getNotCoerced(); - if (notCoerced instanceof GetLexAVM2Item) { - GetLexAVM2Item getLex = (GetLexAVM2Item) notCoerced; - if (localData.abc.constants.getMultiname(multinameIndex).equals(getLex.propertyName) - && (obj instanceof FindPropertyAVM2Item)) { - stack.pop(); - if (isIncrement) { - stack.push(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getLex)); - } else { - stack.push(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getLex)); - } - return; - } - } - if (notCoerced instanceof GetPropertyAVM2Item) { - GetPropertyAVM2Item getProp = (GetPropertyAVM2Item) notCoerced; - if (((FullMultinameAVM2Item) getProp.propertyName).compareSame(multiname)) { - - if (getProp.object instanceof DuplicateItem) { //assembled/TestIncrement3 - if (getProp.object.value == obj) { - getProp.object = obj; - } - } - - if (Objects.equals(obj, getProp.object)) { - stack.pop(); - if (isIncrement) { - stack.push(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getProp)); - } else { - stack.push(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getProp)); - } - return; - } - } - } - } - } - } - } - - if ((value instanceof IncrementAVM2Item) || (value instanceof DecrementAVM2Item)) { - boolean isIncrement = (value instanceof IncrementAVM2Item); - - boolean hasConvert = value.value instanceof ConvertAVM2Item; - if (value.value.getNotCoercedNoDup() instanceof GetLexAVM2Item) { - GetLexAVM2Item getLex = (GetLexAVM2Item) value.value.getNotCoercedNoDup(); - if (localData.abc.constants.getMultiname(multinameIndex).equals(getLex.propertyName) - && (obj instanceof FindPropertyAVM2Item)) { - if (hasConvert) { - if (isIncrement) { - output.add(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getLex)); - } else { - output.add(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getLex)); - } - } else { - if (isIncrement) { - output.add(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getLex)); - } else { - output.add(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getLex)); - } - } - return; - } - } - - if (value.value.getNotCoercedNoDup() instanceof GetPropertyAVM2Item) { - GetPropertyAVM2Item getProp = (GetPropertyAVM2Item) value.value.getNotCoercedNoDup(); - if (((FullMultinameAVM2Item) getProp.propertyName).compareSame(multiname)) { - - if (getProp.object instanceof DuplicateItem) { - if (getProp.object.value == obj) { - getProp.object = obj; - } - } - if (Objects.equals(getProp.object, obj)) { - if (hasConvert) { - if (isIncrement) { - output.add(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getProp)); - } else { - output.add(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getProp)); - } - } else { - if (isIncrement) { - output.add(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getProp)); - } else { - output.add(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getProp)); - } - } - return; - } - } - } - } - //assembled/TestIncrement2 - if (value instanceof DuplicateItem) { - GraphTargetItem duplicated = value.value; - if ((duplicated instanceof IncrementAVM2Item) || (duplicated instanceof DecrementAVM2Item)) { - boolean isIncrement = (duplicated instanceof IncrementAVM2Item); - if (!stack.isEmpty()) { - if (stack.peek() == duplicated) { - GraphTargetItem incrementedProp = duplicated.value; - if (incrementedProp instanceof GetLexAVM2Item) { - GetLexAVM2Item getLex = (GetLexAVM2Item) incrementedProp; - if (localData.abc.constants.getMultiname(multinameIndex).equals(getLex.propertyName) - && (obj instanceof FindPropertyAVM2Item)) { - stack.pop(); - if (isIncrement) { - stack.push(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getLex)); - } else { - stack.push(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getLex)); - } - return; - } - } - if (incrementedProp instanceof GetPropertyAVM2Item) { - GetPropertyAVM2Item getProp = (GetPropertyAVM2Item) incrementedProp; - if (((FullMultinameAVM2Item) getProp.propertyName).compareSame(multiname) - && (Objects.equals(getProp.object, obj))) { - stack.pop(); - if (isIncrement) { - stack.push(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getProp)); - } else { - stack.push(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getProp)); - } - return; - } - } - } - } - } - } - if (value instanceof LocalRegAVM2Item) { - LocalRegAVM2Item valueLocalReg = (LocalRegAVM2Item) value; - LocalRegAVM2Item nameLocalReg = null; - if (multiname.name instanceof LocalRegAVM2Item) { - nameLocalReg = (LocalRegAVM2Item) multiname.name;; - } - if (obj instanceof LocalRegAVM2Item) { - LocalRegAVM2Item objLocalReg = (LocalRegAVM2Item) obj; - - if (!output.isEmpty()) { - if (output.get(output.size() - 1) instanceof SetLocalAVM2Item) { - SetLocalAVM2Item valueSetLocalReg = (SetLocalAVM2Item) output.get(output.size() - 1); - if ((valueSetLocalReg.value instanceof IncrementAVM2Item) - || (valueSetLocalReg.value instanceof DecrementAVM2Item)) { - boolean isIncrement = (valueSetLocalReg.value instanceof IncrementAVM2Item); - if (valueSetLocalReg.value.value instanceof DuplicateItem) { - GraphTargetItem duplicated = valueSetLocalReg.value.value.value; - if (!stack.isEmpty() && stack.peek() == duplicated) { - GraphTargetItem notCoerced = duplicated.getNotCoerced(); - if (notCoerced instanceof GetPropertyAVM2Item) { - GetPropertyAVM2Item getProperty = (GetPropertyAVM2Item) notCoerced; - FullMultinameAVM2Item propertyName = ((FullMultinameAVM2Item) getProperty.propertyName); - SetLocalAVM2Item nameSetLocalReg = null; - if (propertyName.name instanceof SetLocalAVM2Item) { - nameSetLocalReg = (SetLocalAVM2Item) propertyName.name; - } - if (getProperty.object instanceof SetLocalAVM2Item) { - SetLocalAVM2Item objSetLocalReg = (SetLocalAVM2Item) getProperty.object; - - if ((valueLocalReg.regIndex == valueSetLocalReg.regIndex) - && (propertyName.multinameIndex == multinameIndex) - && ((nameLocalReg == null && nameSetLocalReg == null) || (nameLocalReg.regIndex == nameSetLocalReg.regIndex)) - && (objLocalReg.regIndex == objSetLocalReg.regIndex)) { - if (nameSetLocalReg != null) { - propertyName.name = nameSetLocalReg.value; - } - getProperty.object = objSetLocalReg.value; - output.remove(output.size() - 1); - stack.pop(); - if (isIncrement) { - stack.push(new PostIncrementAVM2Item(ins, localData.lineStartInstruction, getProperty)); - } else { - stack.push(new PostDecrementAVM2Item(ins, localData.lineStartInstruction, getProperty)); - } - return; - } - } - } - } - } - } - } - } - - if (!stack.isEmpty()) { - GraphTargetItem checked = checkIncDec(false, multinameIndex, ins, localData, stack.peek(), valueLocalReg, nameLocalReg, objLocalReg); - if (checked != null) { - stack.pop(); - stack.push(checked); - return; - } - } - if (!output.isEmpty()) { - GraphTargetItem checked = checkIncDec(true, multinameIndex, ins, localData, output.get(output.size() - 1), valueLocalReg, nameLocalReg, objLocalReg); - if (checked != null) { - output.remove(output.size() - 1); - output.add(checked); - return; - } - } - } - } - - if (obj.getThroughDuplicate() instanceof ConstructAVM2Item) { - ConstructAVM2Item c = (ConstructAVM2Item) obj.getThroughDuplicate(); - if (c.object instanceof ApplyTypeAVM2Item) { - ApplyTypeAVM2Item at = (ApplyTypeAVM2Item) c.object; - c.args.clear(); - List vals = new ArrayList<>(); - vals.add(value); - c.object = new InitVectorAVM2Item(c.getInstruction(), c.getLineStartIns(), at.params.get(0), vals); - return; - } else if (c.object instanceof InitVectorAVM2Item) { - InitVectorAVM2Item iv = (InitVectorAVM2Item) c.object; - iv.arguments.add(value); - return; - } - } - - /* - GraphTargetItem propertyType = TypeItem.UNBOUNDED; - String multinameStr = localData.abc.constants.getMultiname(multiname.multinameIndex).getName(localData.abc.constants, new ArrayList<>(), true, true); - - for (Trait t : localData.methodBody.traits.traits) { - if (t instanceof TraitSlotConst) { - TraitSlotConst tsc = (TraitSlotConst) t; - if (Objects.equals( - tsc.getName(localData.abc).getName(localData.abc.constants, new ArrayList<>(), true, true), - multinameStr - )) { - propertyType = PropertyAVM2Item.multinameToType(tsc.type_index, localData.abc.constants); - break; - } - } - } - */ - Reference isStatic = new Reference<>(false); - Reference type = new Reference<>(null); - Reference callType = new Reference<>(null); - GetPropertyIns.resolvePropertyType(localData, obj, multiname, isStatic, type, callType); - - SetPropertyAVM2Item result = new SetPropertyAVM2Item(ins, localData.lineStartInstruction, obj, multiname, value, type.getVal(), callType.getVal(), isStatic.getVal()); - handleCompound(localData, obj, multiname, value, output, result); - - SetTypeIns.handleResult(value, stack, output, localData, result, -1, type.getVal()); + public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { + handleSetProperty(false, localData, stack, ins, output, path); } public static void handleCompound(AVM2LocalData localData, GraphTargetItem obj, FullMultinameAVM2Item multiname, GraphTargetItem value, List output, SetTypeAVM2Item result) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AddAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AddAVM2Item.java index 90755f3af..42e4f4df7 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AddAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/AddAVM2Item.java @@ -80,14 +80,14 @@ public class AddAVM2Item extends BinaryOpItem implements CompoundableBinaryOp { @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - if (rightSide instanceof IntegerValueAVM2Item) { + /*if (rightSide instanceof IntegerValueAVM2Item) { IntegerValueAVM2Item iv = (IntegerValueAVM2Item) rightSide; if (iv.value == 1) { return toSourceMerge(localData, generator, leftSide, new AVM2Instruction(0, AVM2Instructions.Increment, null) ); } - } + }*/ return toSourceMerge(localData, generator, leftSide, rightSide, new AVM2Instruction(0, AVM2Instructions.Add, null) ); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NegAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NegAVM2Item.java index 08849534b..75f95e2a9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NegAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/NegAVM2Item.java @@ -51,6 +51,6 @@ public class NegAVM2Item extends UnaryOpItem { @Override public GraphTargetItem returnType() { - return TypeItem.UNBOUNDED; + return TypeItem.NUMBER; } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/SubtractAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/SubtractAVM2Item.java index b8e01ec87..f3caaf1de 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/SubtractAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/operations/SubtractAVM2Item.java @@ -71,14 +71,14 @@ public class SubtractAVM2Item extends BinaryOpItem implements CompoundableBinary @Override public List toSource(SourceGeneratorLocalData localData, SourceGenerator generator) throws CompilationException { - if (rightSide instanceof IntegerValueAVM2Item) { + /*if (rightSide instanceof IntegerValueAVM2Item) { IntegerValueAVM2Item iv = (IntegerValueAVM2Item) rightSide; if (iv.value == 1) { return toSourceMerge(localData, generator, leftSide, new AVM2Instruction(0, AVM2Instructions.Decrement, null) ); } - } + }*/ return toSourceMerge(localData, generator, leftSide, rightSide, new AVM2Instruction(0, AVM2Instructions.Subtract, null) ); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/BinaryOpItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/BinaryOpItem.java index f7c892dde..173271b56 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/BinaryOpItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/BinaryOpItem.java @@ -72,10 +72,10 @@ public abstract class BinaryOpItem extends GraphTargetItem implements BinaryOp { int leftPrecedence = leftSide.getPrecedence(); if (leftPrecedence > precedence && leftPrecedence != GraphTargetItem.NOPRECEDENCE) { writer.append("("); - leftSide.toString(writer, localData, coerceLeft); + leftSide.toString(writer, localData, ""); //coerceLeft); writer.append(")"); } else { - leftSide.toString(writer, localData, coerceLeft); + leftSide.toString(writer, localData, ""); //coerceLeft); } writer.append(" "); @@ -85,10 +85,10 @@ public abstract class BinaryOpItem extends GraphTargetItem implements BinaryOp { int rightPrecedence = rightSide.getPrecedence(); if (rightPrecedence >= precedence && rightPrecedence != GraphTargetItem.NOPRECEDENCE) { writer.append("("); - rightSide.toString(writer, localData, coerceRight); + rightSide.toString(writer, localData, ""); //coerceRight); writer.append(")"); } else { - rightSide.toString(writer, localData, coerceRight); + rightSide.toString(writer, localData, ""); //coerceRight); } return writer; } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java index cdb0b4550..566ec3e35 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/model/UnaryOpItem.java @@ -53,10 +53,10 @@ public abstract class UnaryOpItem extends GraphTargetItem implements UnaryOp { if (value != null) { if (value.getPrecedence() > precedence) { writer.append("("); - value.toString(writer, localData, coerce); + value.toString(writer, localData, ""); //coerce); writer.append(")"); } else { - value.toString(writer, localData, coerce); + value.toString(writer, localData, ""); //coerce); } } else { writer.append("null"); 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 7c0a50c8a..5996854c7 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 @@ -164,9 +164,9 @@ public class ActionScript3ClassicDecompileTest extends ActionScript3DecompileTes + "trace(\"arr[2] += 5\");\r\n" + "b[2] += 5;\r\n" + "trace(\"arr[call()] /= 5\");\r\n" - + "b[this.calc()] = Number(b[this.calc()]) / 5;\r\n" + + "b[this.calc()] = b[this.calc()] / 5;\r\n" + "trace(\"arr[call()][call()] &= 10;\");\r\n" - + "b[this.calc()][this.calc()] = Number(b[this.calc()][this.calc()]) & 10;\r\n" + + "b[this.calc()][this.calc()] = b[this.calc()][this.calc()] & 10;\r\n" + "try\r\n" + "{\r\n" + "trace(\"in try\");\r\n"