From 4dc28cdebea710529537567a1a7e97cbe32327fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Wed, 27 Jan 2021 10:09:11 +0100 Subject: [PATCH] increments/decrements, chained assignments fixes --- .../decompiler/flash/abc/avm2/AVM2Code.java | 4 +- .../abc/avm2/instructions/SetTypeIns.java | 45 ++++++++- .../localregs/SetLocalTypeIns.java | 40 +++----- .../instructions/other/SetGlobalSlotIns.java | 2 +- .../instructions/other/SetPropertyIns.java | 27 +++++- .../avm2/instructions/other/SetSlotIns.java | 2 +- .../avm2/instructions/other/SetSuperIns.java | 2 +- .../flash/abc/avm2/model/AVM2Item.java | 25 ++++- .../abc/avm2/model/CallSuperAVM2Item.java | 2 +- .../abc/avm2/model/ConstructPropAVM2Item.java | 2 +- .../abc/avm2/model/GetSuperAVM2Item.java | 2 +- .../abc/avm2/model/LocalRegAVM2Item.java | 3 +- .../abc/avm2/model/SetSuperAVM2Item.java | 14 +-- .../custom/abc/custom-0/custom-0.main.abc | Bin 1058 -> 1925 bytes .../custom/abc/custom-0/custom-0.main.asasm | 4 + .../custom-0/tests/TestForEach.class.asasm | 86 ++++++++++++++++++ .../custom-0/tests/TestForEach.script.asasm | 29 ++++++ .../tests/TestForEachCoerced.class.asasm | 80 ++++++++++++++++ .../tests/TestForEachCoerced.script.asasm | 29 ++++++ .../custom-0/tests/TestIncrement2.class.asasm | 75 +++++++++++++++ .../tests/TestIncrement2.script.asasm | 29 ++++++ .../custom-0/tests/TestSetSlotDup.class.asasm | 83 +++++++++++++++++ .../tests/TestSetSlotDup.script.asasm | 29 ++++++ .../ffdec_lib/testdata/custom/bin/custom.swf | Bin 995 -> 1456 bytes 24 files changed, 565 insertions(+), 49 deletions(-) create mode 100644 libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEach.class.asasm create mode 100644 libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEach.script.asasm create mode 100644 libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEachCoerced.class.asasm create mode 100644 libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEachCoerced.script.asasm create mode 100644 libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestIncrement2.class.asasm create mode 100644 libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestIncrement2.script.asasm create mode 100644 libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSetSlotDup.class.asasm create mode 100644 libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSetSlotDup.script.asasm 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 02a3ca4f2..98057d1dd 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 @@ -247,6 +247,7 @@ import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.DXNSLateIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXAttrIns; import com.jpexs.decompiler.flash.abc.avm2.instructions.xml.EscXElemIns; +import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; @@ -1609,10 +1610,11 @@ public class AVM2Code implements Cloneable { } }*/ if ((ins.definition instanceof SetLocalTypeIns) && (ip + 1 <= end)) { // set_local_x,get_local_x.. no other local_x get + AVM2Instruction insAfter = code.get(ip + 1); Set usages = setLocalPosToGetLocalPos.containsKey(ip) ? setLocalPosToGetLocalPos.get(ip) : new HashSet<>(); - if (usages.size() == 1 && (usages.iterator().next().equals(ip + 1)) && (insAfter.definition instanceof GetLocalTypeIns) && (((GetLocalTypeIns) insAfter.definition).getRegisterId(insAfter) == ((SetLocalTypeIns) ins.definition).getRegisterId(ins))) { + if (!AVM2Item.mustStayIntact2(stack.peek()) && usages.size() == 1 && (usages.iterator().next().equals(ip + 1)) && (insAfter.definition instanceof GetLocalTypeIns) && (((GetLocalTypeIns) insAfter.definition).getRegisterId(insAfter) == ((SetLocalTypeIns) ins.definition).getRegisterId(ins))) { ip += 2; continue iploop; } else { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java index b0c690dae..b40b62bcc 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/SetTypeIns.java @@ -12,13 +12,22 @@ * 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; +import com.jpexs.decompiler.flash.abc.AVM2LocalData; import com.jpexs.decompiler.flash.abc.avm2.model.AVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.CoerceAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.SetLocalAVM2Item; import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.graph.DottedChain; +import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.DuplicateItem; import java.util.HashMap; import java.util.List; import java.util.Stack; @@ -30,4 +39,38 @@ import java.util.Stack; public interface SetTypeIns { public abstract String getObject(Stack stack, ABC abc, AVM2Instruction ins, List output, MethodBody body, HashMap localRegNames, List fullyQualifiedNames) throws InterruptedException; + + public static void handleResult(GraphTargetItem value, TranslateStack stack, List output, AVM2LocalData localData, GraphTargetItem result, int regId) { + GraphTargetItem notCoercedValue = value; + if ((value instanceof CoerceAVM2Item) || (value instanceof ConvertAVM2Item)) { + notCoercedValue = value.value; + } + + if (notCoercedValue instanceof DuplicateItem) { + GraphTargetItem insideDup = notCoercedValue.value; + if (!AVM2Item.mustStayIntact1(insideDup.getNotCoerced())) { + if (!stack.isEmpty() && stack.peek() == insideDup) { + stack.pop(); + if ((value instanceof CoerceAVM2Item) || (value instanceof ConvertAVM2Item)) { + value.value = insideDup; + } else { + value = insideDup; + } + + result.value = value; + //GraphTargetItem result = new SetLocalAVM2Item(ins, localData.lineStartInstruction, regId, value); + + if (regId > -1 && AVM2Item.mustStayIntact2(insideDup.getNotCoerced())) { //hack + output.add(result); + stack.push(new LocalRegAVM2Item(null, localData.lineStartInstruction, regId, value)); + return; + } + + stack.push(result); + return; + } + } + } + output.add(result); + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java index 1dfaafc80..049e7f0d6 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/localregs/SetLocalTypeIns.java @@ -31,10 +31,13 @@ import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.IncrementAVM2Item; 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.NextNameAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.NextValueAVM2Item; 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.SetTypeAVM2Item; +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.types.MethodBody; @@ -134,41 +137,26 @@ public abstract class SetLocalTypeIns extends InstructionDefinition implements S } } - if (localData.getSetLocalUsages(localData.code.adr2pos(ins.getAddress())).isEmpty() && (value instanceof DuplicateItem)) { + /*if (localData.getSetLocalUsages(localData.code.adr2pos(ins.getAddress())).isEmpty() && (value instanceof DuplicateItem)) { return; - } - - GraphTargetItem notCoercedValue = value; - if ((value instanceof CoerceAVM2Item) || (value instanceof ConvertAVM2Item)) { - notCoercedValue = value.value; - } - - if (notCoercedValue instanceof DuplicateItem) { - GraphTargetItem insideDup = notCoercedValue.value; - if (!stack.isEmpty() && stack.peek() == insideDup) { - stack.pop(); - if ((value instanceof CoerceAVM2Item) || (value instanceof ConvertAVM2Item)) { - value.value = insideDup; - } else { - value = insideDup; - } - - GraphTargetItem result = new SetLocalAVM2Item(ins, localData.lineStartInstruction, regId, value); - stack.push(result); - return; - } - } + }*/ GraphTargetItem result = new SetLocalAVM2Item(ins, localData.lineStartInstruction, regId, value); - output.add(result); + + SetTypeIns.handleResult(value, stack, output, localData, result, regId); } @Override - public int getStackPopCount(AVM2Instruction ins, ABC abc) { + public int getStackPopCount(AVM2Instruction ins, ABC abc + ) { return 1; } @Override - public String getObject(Stack stack, ABC abc, AVM2Instruction ins, List output, MethodBody body, HashMap localRegNames, List fullyQualifiedNames) { + public String getObject(Stack stack, ABC abc, + AVM2Instruction ins, List output, + MethodBody body, HashMap localRegNames, + List fullyQualifiedNames + ) { return AVM2Item.localRegName(localRegNames, getRegisterId(ins)); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetGlobalSlotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetGlobalSlotIns.java index 77d14ab97..7e7f60597 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetGlobalSlotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetGlobalSlotIns.java @@ -46,7 +46,7 @@ public class SetGlobalSlotIns extends InstructionDefinition implements SetTypeIn public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { GraphTargetItem value = stack.pop(); GraphTargetItem result = new SetGlobalSlotAVM2Item(ins, localData.lineStartInstruction, ins.operands[0], value); - output.add(result); + SetTypeIns.handleResult(value, stack, output, localData, result, -1); } @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 2db1f4396..633fc635c 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 @@ -111,6 +111,7 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns 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) { @@ -134,7 +135,31 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns } } } + } + //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)) { + stack.pop(); + if (isIncrement) { + stack.push(new PreIncrementAVM2Item(ins, localData.lineStartInstruction, getLex)); + } else { + stack.push(new PreDecrementAVM2Item(ins, localData.lineStartInstruction, getLex)); + } + return; + } + } + } + } + } } if (value instanceof LocalRegAVM2Item) { @@ -228,7 +253,7 @@ public class SetPropertyIns extends InstructionDefinition implements SetTypeIns } GraphTargetItem result = new SetPropertyAVM2Item(ins, localData.lineStartInstruction, obj, multiname, value); - output.add(result); + SetTypeIns.handleResult(value, stack, output, localData, result, -1); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java index 674a89c49..7ee425d7e 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSlotIns.java @@ -160,7 +160,7 @@ public class SetSlotIns extends InstructionDefinition implements SetTypeIns { } GraphTargetItem result = new SetSlotAVM2Item(ins, localData.lineStartInstruction, obj, objnoreg, slotIndex, slotname, value); - output.add(result); + SetTypeIns.handleResult(value, stack, output, localData, result, -1); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSuperIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSuperIns.java index 2186f58d2..36e6f8237 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSuperIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/other/SetSuperIns.java @@ -55,7 +55,7 @@ public class SetSuperIns extends InstructionDefinition implements SetTypeIns { FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins); GraphTargetItem obj = stack.pop(); GraphTargetItem result = new SetSuperAVM2Item(ins, localData.lineStartInstruction, value, obj, multiname); - output.add(result); + SetTypeIns.handleResult(value, stack, output, localData, result, -1); } @Override diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java index 893b5d42b..5de34234d 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/AVM2Item.java @@ -22,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.AVM2Instructions; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; +import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.parser.script.AVM2SourceGenerator; import com.jpexs.decompiler.flash.configuration.Configuration; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; @@ -72,7 +73,7 @@ public abstract class AVM2Item extends GraphTargetItem { } protected GraphTextWriter formatProperty(GraphTextWriter writer, GraphTargetItem object, GraphTargetItem propertyName, LocalData localData) throws InterruptedException { - boolean empty = object instanceof FindPropertyAVM2Item; + boolean empty = object.getThroughDuplicate() instanceof FindPropertyAVM2Item; if (object instanceof LocalRegAVM2Item) { if (((LocalRegAVM2Item) object).computedValue != null) { if (((LocalRegAVM2Item) object).computedValue.getThroughNotCompilable() instanceof FindPropertyAVM2Item) { @@ -81,8 +82,8 @@ public abstract class AVM2Item extends GraphTargetItem { } } - if (object instanceof FindPropertyAVM2Item) { - FindPropertyAVM2Item fp = (FindPropertyAVM2Item) object; + if (object.getThroughDuplicate() instanceof FindPropertyAVM2Item) { + FindPropertyAVM2Item fp = (FindPropertyAVM2Item) object.getThroughDuplicate(); if (fp.propertyName instanceof FullMultinameAVM2Item) { propertyName = fp.propertyName; } @@ -202,4 +203,22 @@ public abstract class AVM2Item extends GraphTargetItem { return true; } + public static boolean mustStayIntact1(GraphTargetItem target) { + target = target.getNotCoerced(); + if (target instanceof ExceptionAVM2Item) { + return true; + } + return false; + } + + public static boolean mustStayIntact2(GraphTargetItem target) { + target = target.getNotCoerced(); + if (target instanceof NextValueAVM2Item) { + return true; + } + if (target instanceof NextNameAVM2Item) { + return true; + } + return false; + } } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java index 7ef55c86a..b0cc50af9 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/CallSuperAVM2Item.java @@ -55,7 +55,7 @@ public class CallSuperAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { - if (!receiver.toString().equals("this") && !(receiver instanceof FindPropertyAVM2Item)) { + if (!receiver.toString().equals("this") && !(receiver.getThroughDuplicate() instanceof FindPropertyAVM2Item)) { receiver.toString(writer, localData); writer.append("."); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java index 01578c000..81ec70778 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/ConstructPropAVM2Item.java @@ -53,7 +53,7 @@ public class ConstructPropAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { writer.append("new "); - if (!(object instanceof FindPropertyAVM2Item)) { + if (!(object.getThroughDuplicate() instanceof FindPropertyAVM2Item)) { object.toString(writer, localData); writer.append("."); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/GetSuperAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/GetSuperAVM2Item.java index d40a2bebe..55ad52ef4 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/GetSuperAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/GetSuperAVM2Item.java @@ -48,7 +48,7 @@ public class GetSuperAVM2Item extends AVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { if (!object.toString().equals("this")) { - if (!(object instanceof FindPropertyAVM2Item)) { + if (!(object.getThroughDuplicate() instanceof FindPropertyAVM2Item)) { object.toString(writer, localData); writer.append("."); } diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/LocalRegAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/LocalRegAVM2Item.java index fc897bf03..3453be524 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/LocalRegAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/LocalRegAVM2Item.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; import com.jpexs.decompiler.flash.SourceGeneratorLocalData; diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSuperAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSuperAVM2Item.java index a707a2eea..ac154a0ed 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSuperAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/SetSuperAVM2Item.java @@ -16,22 +16,14 @@ */ package com.jpexs.decompiler.flash.abc.avm2.model; -import com.jpexs.decompiler.flash.abc.ABC; -import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; -import com.jpexs.decompiler.flash.abc.avm2.instructions.SetTypeIns; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.DeclarationAVM2Item; -import com.jpexs.decompiler.flash.abc.types.MethodBody; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; -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.TypeItem; import com.jpexs.decompiler.graph.model.LocalData; -import java.util.HashMap; -import java.util.List; -import java.util.Stack; /** * @@ -78,8 +70,10 @@ public class SetSuperAVM2Item extends AVM2Item implements SetTypeAVM2Item { @Override public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException { if (!object.toString().equals("this")) { - object.toString(writer, localData); - writer.append("."); + if (!(object.getThroughDuplicate() instanceof FindPropertyAVM2Item)) { + object.toString(writer, localData); + writer.append("."); + } } writer.append("super."); propertyName.toString(writer, localData); diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.abc b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.abc index 1479e4356824aeb86d7ffd8b09c1ad3274edfc57..1412e02c7e2d0c1a056428316e1c173387047ead 100644 GIT binary patch literal 1925 zcmb_b-BQ~|6h3FQtJTWC@~;p$Krs0+309!(1$PWkCNu5$g3Q!6G?HZzy9J4{1T(qI zE9A|b%p`q;_AThH4Hz|@UR9boI_EpP-*@($RT;KHKHuxT!Ea%Z>PdVNMhX4dA4kBB zuEQwRPcA3pG_>A?NqTs7xt}ECcadC_<`nW{JUQ}%QRRVu5Qmc>92OMxItnJCT3pOT zJG1a4Oi#{ZMM}rfIHecwqr_ANT!iT;9qr>nQ$ z4#&ymx&MBCj7BCph@(`VC!CaK2U0md4MyR_dL5z zw&AC7l7@0S4hm;7HQFA|wU#r{UPiP1AG!N_RneNy77fxM zHnF$uuI<{d>>bC-BPnnlg+|O$)vA;X*{9fM4HdHH%-S=%G_#Jf zI~+2;8+M~xHCiNT5B#N;H$NnR8PM~CAEXF4xD;g3q9LIk5?iHPS!?CP8s zcz%noY;r7de92jrvl?d&ZZK}td8^3_PX#i8T%aLP2s8!egsusW!ceg=QRGnMQM@24 z>d#jXk~J_epPxs!mSiG;|10KtS(t!mBgoT=A~4htbXnIr2<4ix&{ZfXwyFN? zziw{iGRaxGlX{_~p7gcW$dGV(A!TKxDoW~^YC~XnO93xelmZ_Z8y_Bb0{zqH0qZ&P zXELlmZ*C+}^^X6g;(ywwt&xy$ZNXp9@HZ5{Bm3fd>|^JYZTYNCYD{*z(yPF++}gZj z>?+1*ebyS~By2AjmokiwVw891m(CZr%>w3GFP;rp=R@h!)&=&KiD&gz;23ZNumsC@ Pxz7*Z7V`BZcd?gI06j zLGc@_=D&Q0bOQxT6P^yQue&uI5en+H2$Ap+35Nu+v2%xTOiFVDSt)KKkB}!0Ifj%+ z$|n^NDWWC|&DNqNJAz5@gFSlnkJW{$3kJPE_(ZBx|J%-3N|#+gY#|7Z?160vj)NQl z*P{!dz<`t}6#}7FfDLpM2+!IK%PM_k?_5b_cT%O*6=cJX0jQ<~E&GPKpLwfBwW6sn ztWZe7ZcwH3=9zBRv=lb$NtNc1VVd>Qtes|Insw65O|y6g<5OMB<0t)m6#SS5Xia2I rvd$XRrf7!aYkmB#FD}IW)5Ba`F2p-?xiD7QI4hG{*`JB=wPWdD(WF;k diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.asasm index 6e88763e1..47f80cbdc 100644 --- a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.asasm +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/custom-0.main.asasm @@ -6,5 +6,9 @@ program #include "Main.script.asasm" #include "tests/TestDupAssignment.script.asasm" #include "tests/TestIncrement.script.asasm" + #include "tests/TestForEach.script.asasm" + #include "tests/TestForEachCoerced.script.asasm" + #include "tests/TestIncrement2.script.asasm" + #include "tests/TestSetSlotDup.script.asasm" ; place to add next end ; program diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEach.class.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEach.class.asasm new file mode 100644 index 000000000..beb944588 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEach.class.asasm @@ -0,0 +1,86 @@ +class + refid "tests:TestForEach" + instance QName(PackageNamespace("tests"), "TestForEach") + extends QName(PackageNamespace(""), "Object") + flag SEALED + flag PROTECTEDNS + protectedns ProtectedNamespace("tests:TestForEach") + iinit + refid "tests:TestForEach/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:TestForEach/instance/run" + returns QName(PackageNamespace(""), "void") + body + maxstack 2 + localcount 4 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + pushundefined + setlocal 5 + pushbyte 0 + setlocal2 + pushbyte 0 + setlocal3 + pushbyte 0 + setlocal 7 + getlocal 5 + setlocal 6 + jump ofs0043 +ofs0017: + label + getlocal 6 + getlocal 7 + nextvalue + dup + setlocal 4 + pushnull + ifeq ofs0043 + getlocal 4 + setlocal2 +ofs0043: + hasnext2 6, 7 + iftrue ofs0017 + pushbyte 0 + setlocal3 + returnvoid + end ; code + end ; body + end ; method + end ; trait + end ; instance + cinit + refid "tests:TestForEach/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/custom/abc/custom-0/tests/TestForEach.script.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEach.script.asasm new file mode 100644 index 000000000..094cd40bb --- /dev/null +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEach.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestForEach/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestForEach", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestForEach"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestForEach" + popscope + initproperty QName(PackageNamespace("tests"), "TestForEach") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestForEach") + #include "TestForEach.class.asasm" + end ; trait +end ; script diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEachCoerced.class.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEachCoerced.class.asasm new file mode 100644 index 000000000..12395e386 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEachCoerced.class.asasm @@ -0,0 +1,80 @@ +class + refid "tests:TestForEachCoerced" + instance QName(PackageNamespace("tests"), "TestForEachCoerced") + extends QName(PackageNamespace(""), "Object") + flag SEALED + flag PROTECTEDNS + protectedns ProtectedNamespace("tests:TestForEachCoerced") + iinit + refid "tests:TestForEachCoerced/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:TestForEachCoerced/instance/run" + returns QName(PackageNamespace(""), "void") + body + maxstack 2 + localcount 4 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + pushbyte 0 + setlocal 8 + getlex QName(PrivateNamespace("somens"),"someprop") + setlocal 7 + jump ofs0054 +ofs0042: + label + getlocal 7 + getlocal 8 + nextvalue + coerce QName(PackageNamespace("somens"),"SomeClass") + dup + setlocal 6 + getlocal1 + getlocal2 + getlocal 5 + callpropvoid QName(Namespace("somens"),"methodname"), 3 +ofs0054: + hasnext2 7, 8 + iftrue ofs0042 + + returnvoid + end ; code + end ; body + end ; method + end ; trait + end ; instance + cinit + refid "tests:TestForEachCoerced/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/custom/abc/custom-0/tests/TestForEachCoerced.script.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEachCoerced.script.asasm new file mode 100644 index 000000000..bca0c08bd --- /dev/null +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestForEachCoerced.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestForEachCoerced/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestForEachCoerced", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestForEachCoerced"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestForEachCoerced" + popscope + initproperty QName(PackageNamespace("tests"), "TestForEachCoerced") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestForEachCoerced") + #include "TestForEachCoerced.class.asasm" + end ; trait +end ; script diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestIncrement2.class.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestIncrement2.class.asasm new file mode 100644 index 000000000..605f96319 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestIncrement2.class.asasm @@ -0,0 +1,75 @@ +class + refid "tests:TestIncrement2" + instance QName(PackageNamespace("tests"), "TestIncrement2") + extends QName(PackageNamespace(""), "Object") + flag SEALED + flag PROTECTEDNS + protectedns ProtectedNamespace("tests:TestIncrement2") + iinit + refid "tests:TestIncrement2/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:TestIncrement2/instance/run" + returns QName(PackageNamespace(""), "void") + body + maxstack 2 + localcount 4 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + + getlocal0 + pushscope + getlex QName(PrivateNamespace("somens"),"loadCount") + increment + dup + findpropstrict QName(PrivateNamespace("somens"),"loadCount") + swap + setproperty QName(PrivateNamespace("somens"),"loadCount") + pushbyte 2 + ifne ofs001b + findpropstrict QName(ProtectedNamespace("somens"),"somemethod") + callpropvoid QName(ProtectedNamespace("somens"),"somemethod"), 0 +ofs001b: + returnvoid + + returnvoid + end ; code + end ; body + end ; method + end ; trait + end ; instance + cinit + refid "tests:TestIncrement2/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/custom/abc/custom-0/tests/TestIncrement2.script.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestIncrement2.script.asasm new file mode 100644 index 000000000..b7ab5cc48 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestIncrement2.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestIncrement2/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestIncrement2", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestIncrement2"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestIncrement2" + popscope + initproperty QName(PackageNamespace("tests"), "TestIncrement2") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestIncrement2") + #include "TestIncrement2.class.asasm" + end ; trait +end ; script diff --git a/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSetSlotDup.class.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSetSlotDup.class.asasm new file mode 100644 index 000000000..5002a098e --- /dev/null +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSetSlotDup.class.asasm @@ -0,0 +1,83 @@ +class + refid "tests:TestSetSlotDup" + instance QName(PackageNamespace("tests"), "TestSetSlotDup") + extends QName(PackageNamespace(""), "Object") + flag SEALED + flag PROTECTEDNS + protectedns ProtectedNamespace("tests:TestSetSlotDup") + iinit + refid "tests:TestSetSlotDup/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:TestSetSlotDup/instance/run" + returns QName(PackageNamespace(""), "void") + body + maxstack 2 + localcount 4 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + newactivation + dup + setlocal1 + pushscope + pushbyte 5 + setlocal 5 + getlex QName(PackageInternalNs("myns"),"myname") + pushstring "okay" + getlocal 5 + dup + coerce QName(PackageNamespace(""),"int") + getlocal1 + swap + setslot 1 + callpropvoid QName(PackageNamespace(""),"somemethod"), 2 + getlex QName(PackageInternalNs("myns"),"myname") + callpropvoid QName(PackageNamespace(""),"start"), 0 + returnvoid + end ; code + + trait slot QName(PackageInternalNs("myns"),"myslot") + slotid 1 + type QName(PackageNamespace(""),"int") + ;value Undefined() + end ; trait + + end ; body + end ; method + end ; trait + end ; instance + cinit + refid "tests:TestSetSlotDup/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/custom/abc/custom-0/tests/TestSetSlotDup.script.asasm b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSetSlotDup.script.asasm new file mode 100644 index 000000000..4cfe26f86 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/custom/abc/custom-0/tests/TestSetSlotDup.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestSetSlotDup/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestSetSlotDup", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestSetSlotDup"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestSetSlotDup" + popscope + initproperty QName(PackageNamespace("tests"), "TestSetSlotDup") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestSetSlotDup") + #include "TestSetSlotDup.class.asasm" + end ; trait +end ; script diff --git a/libsrc/ffdec_lib/testdata/custom/bin/custom.swf b/libsrc/ffdec_lib/testdata/custom/bin/custom.swf index 987881428221a63622ab16fb03e810cb75dc596f..d56639ada274f4ed89ba5f015cce0c3b98638aec 100644 GIT binary patch literal 1456 zcmV;h1yA}zS5qXv2><|i+O<{NZrer>-6gqPuI@KWvTWIMti*|Ii?o~uh~WrzEhk9P zRzMw~MgTXWDB5BpkpfBi^3;4n^9lWuKJ}?DN`R!F(Ef!xOIenc6n!fNEqBhIJu^Eq zBrgyhA(R^+w1iP3Igb$fIsFGlXxHtW?0nyNTDs`>Y;OmwCu?2bAMB{=`T2SEe7own zr|Q<@$B$L5rq*hkz}WOIZC}6Gw7u1}dLYm+J;SvIzU9~@ZtHDl=s#IoyH@QOH==`~ z+Y2N+hHCcAzG?fOx>el*p^mY0;<$a?uj_+B&oXo_r(SG&UB`HRuAiBkCq3Qk?y6HF z-{V_;&#dotoVHnd+A}Xo4@-N~{Q-MS;pEOV(E6=o>U?+AaQf=Nbvi=>Vmbk-VDs%Q zTw*Y6_bjh#y7i&`+IG&zE~Y5w7_O=N&Maes@%5f=pAPj?vwrYhuy$hyG3vfq|5~?8 zwMQGJnpWEyhr!WZ^^Q_(Bq2j-X zzSS)o{g(NKA_O)%arM5rg%YUBXd^7pN^!&zf zu;+Q!sm&`G=EzgWJehVUFm z@c{a!-*q~~2acBu#+}c+$MzbHgT|{D%~yvn_MRO?86hbUWM`~>2O8J1O*bAK zh_C6s0aZ&rw|&#q4c|I5$5eI*?)RbLJgg`5PAAy#jpg|!Y{%_r(2Ld1Sbbr}+L`fL z{*Serc$Q~LpGA|IT^|=BG6qc^nYVb`*!kpmE7!d~?eo3EZMCLpkJR?i>iL!}TDH%6 zj^5dKhPEFX=iP?Jkf9din+Fw=oY(qg8cOG!nKKy?-Jz}UiopXkAf6A+%tzNxPOEm^ z75UGQ>pn?O7jF6^^DkKK7C7x3;zPzv>CCY@ce7G9q1?$OvI_(elr80?ya+QP7t1FL zVqvjREG!k43oCr}<`+|htdJM-)x4V5@>}^@AsN9!l**WiLMWb2rV<%BFi30$R7e;L zlBmoDw^*5E`JLo~F&~Wc!C2s9jbcpkLy9YOAx|S^ibX0=DkxN7R0vTaOoa%G3KSP8 zUZq5)(R*|$&Qby+5}Oy;1A%SJltyV}oi5&`I8N~3IT~GKm@rHk zRv2ashZqhsS!5J5h1)EISs1ejW*fpHy1uYbLJE#V(Cte==zp=PoM0h@aULT$EsG(7 zMT}&KYXvbr4MCvGD9WcX2)Klje42u&@1Qw8%|i66Xr50C@UBA&iokm;gYt-qSe7uN zm`VtTaY#Z!94itM)0jy}%Hgnt$O4W?NM3{x6ef z;bNBptW4$Dj9iGz&5cha4J&VtrFC8UF}AM9U@<%qt8%fsM?$e10yr`ii_VC}xY+hc zTQNu(eJrCt%gCT@V#tXk_-)H=x>_-$QX0NKZRul8rpdpru7Czx;}cgK+||7!vDj4r zPE1`TXI!PYtNT0+hSHihXd=Zu(6+Mr=1#?s-@R{>W&s{1CHdFY74Xv&{Y|dFb|e+M z4B*UEe{M!U%k>LjX)W@$a!l5BQWi1|*AY%T&1uOb{r3lnjTi$6G$i`@vXU7CN9gKzGa KF!={75=DCpSIkfV literal 995 zcmV<9104KAS5qWh1^@tf+I>{rZre5#CM8M~75~PG?Kny6t^oqHv!%F0ff$J~uTF~$ z+X5`P2nuAiEYY!6SrQ~VPOkP0dxSm7u6DH>qd@lzdy9;e5<6~(60pSYobP<+kmp#} z0M7uZgaAB(pjX@g0Q^?^8v<|;Im7nPz1Q{YvFFEajt+N6jD>B(m`5FC%T^f7) z`}>C3GFq($XEfp)pIO%pKYqH~Nd$T{wj(!WZs6Aiwg$n39q#VlsXF#tG@L|UBI(!$ z_2`)TEH?IO(N5P1 z2DJX#qu2Fs>fJ?r!cHlI>?{iHJUFH$qMLRwHo_=yCN{5W$fc6thao~DoD4iS9?_^X z@!$KwG)=Lv3XUC7iv`P!dzS-9cj26#m%zBfs8^`XYFItxsmSdkEO(5j@ zE>jpc#g*jQ{wyHZ?e&g&@6Jx%ot|~y9A$fM9D3GGnytKqUIl!}T%Shyqz2)$n9Xmv zcj&W=HU zb5#Ric7j2HmvE8oXND`YAwJ1UoF~Z=(epF&B6n}j39~G5si!lOf<83+>t?@b_Dg1e z)$HqLzj_X~lQoh#6+vD|npA-hDQc3GBUM63sm#nB@Nq}~=fku3<0}7uU*tcW