From b0962137f930b3e47c78ca0b6737fa3cde0f95d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Sat, 4 Dec 2021 09:15:19 +0100 Subject: [PATCH] declarations on activation object properties --- .../decompiler/flash/abc/avm2/AVM2Code.java | 39 ++++++++++++++++-- .../model/clauses/DeclarationAVM2Item.java | 36 ++++++++++++++++ .../ActionScript3AssembledDecompileTest.java | 2 +- .../as3_assembled-0/as3_assembled-0.main.abc | Bin 7230 -> 7253 bytes .../tests/TestActivationProps.class.asasm | 7 ++++ .../as3_assembled/bin/as3_assembled.swf | Bin 4362 -> 4378 bytes 6 files changed, 80 insertions(+), 4 deletions(-) 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 49d9c28ed..699cb8955 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 @@ -250,6 +250,7 @@ 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.CoerceAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.ConvertAVM2Item; +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.InitPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; @@ -1861,7 +1862,7 @@ public class AVM2Code implements Cloneable { return assignment; } - private void injectDeclarations(List items, int minreg, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, ABC abc, MethodBody body) { + private void injectDeclarations(List items, int minreg, DeclarationAVM2Item[] declaredRegisters, List declaredSlots, List declaredSlotsDec, List declaredProperties, List declaredPropsDec, ABC abc, MethodBody body) { for (int i = 0; i < items.size(); i++) { GraphTargetItem currentItem = items.get(i); List itemsOnLine = new ArrayList<>(); @@ -1905,6 +1906,38 @@ public class AVM2Code implements Cloneable { } } } + if (subItem instanceof SetPropertyAVM2Item) { + SetPropertyAVM2Item sp = (SetPropertyAVM2Item) subItem; + if (sp.object instanceof FindPropertyAVM2Item) { + if (sp.propertyName instanceof FullMultinameAVM2Item) { + FullMultinameAVM2Item propName = (FullMultinameAVM2Item) sp.propertyName; + if (!declaredProperties.contains(propName.resolvedMultinameName)) { + for (int t = 0; t < body.traits.traits.size(); t++) { + if (body.traits.traits.get(t).getName(abc).getName(abc.constants, new ArrayList(), true, false) + .equals(propName.resolvedMultinameName)) { + if (body.traits.traits.get(t) instanceof TraitSlotConst) { + GraphTargetItem type = PropertyAVM2Item.multinameToType(((TraitSlotConst) body.traits.traits.get(t)).type_index, abc.constants); + DeclarationAVM2Item d = new DeclarationAVM2Item(subItem, type); + sp.setDeclaration(d); + declaredPropsDec.add(d); + declaredProperties.add(propName.resolvedMultinameName); + if (subItem == currentItem) { + items.set(i, d); + } else { + d.showValue = false; + items.add(i, d); + i++; + } + } + } + } + } else { + int idx = declaredProperties.indexOf(propName.resolvedMultinameName); + sp.setDeclaration(declaredPropsDec.get(idx)); + } + } + } + } if (subItem instanceof SetSlotAVM2Item) { SetSlotAVM2Item ssti = (SetSlotAVM2Item) subItem; if (ssti.scope instanceof NewActivationAVM2Item) { @@ -1942,7 +1975,7 @@ public class AVM2Code implements Cloneable { if (currentItem instanceof Block) { Block blk = (Block) currentItem; for (List sub : blk.getSubs()) { - injectDeclarations(sub, minreg, declaredRegisters, declaredSlots, declaredSlotsDec, abc, body); + injectDeclarations(sub, minreg, declaredRegisters, declaredSlots, declaredSlotsDec, declaredProperties, declaredPropsDec, abc, body); } } } @@ -2088,7 +2121,7 @@ public class AVM2Code implements Cloneable { // //int minreg = abc.method_info.get(body.method_info).getMaxReservedReg() + 1; - injectDeclarations(list, 1, d, new ArrayList<>(), new ArrayList<>(), abc, body); + injectDeclarations(list, 1, d, new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), new ArrayList<>(), abc, body); int lastPos = list.size() - 1; if (lastPos < 0) { diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java index 3416ad192..c200570d8 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/model/clauses/DeclarationAVM2Item.java @@ -16,12 +16,15 @@ */ package com.jpexs.decompiler.flash.abc.avm2.model.clauses; +import com.jpexs.decompiler.flash.IdentifiersDeobfuscation; 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; import com.jpexs.decompiler.flash.abc.avm2.model.GetSlotAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.LocalRegAVM2Item; 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.SetSlotAVM2Item; import com.jpexs.decompiler.flash.helpers.GraphTextWriter; import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; @@ -148,6 +151,39 @@ public class DeclarationAVM2Item extends AVM2Item { } return writer; } + + if (assignment instanceof SetPropertyAVM2Item) { + SetPropertyAVM2Item spti = (SetPropertyAVM2Item) assignment; + HighlightData srcData = getSrcData(); + srcData.localName = ((FullMultinameAVM2Item) spti.propertyName).resolvedMultinameName; + srcData.declaration = true; + + GraphTargetItem val = spti.value; + GraphTargetItem coerType = TypeItem.UNBOUNDED; + if (spti.value instanceof CoerceAVM2Item) { + coerType = ((CoerceAVM2Item) spti.value).typeObj; + } + if (spti.value instanceof ConvertAVM2Item) { + coerType = ((ConvertAVM2Item) spti.value).type; + } + //strip coerce if its declared as this type + if (coerType.equals(type) && !coerType.equals(TypeItem.UNBOUNDED)) { + val = val.value; + } + + srcData.declaredType = (type instanceof TypeItem) ? ((TypeItem) type).fullTypeName : DottedChain.ALL; + writer.append("var "); + writer.append(IdentifiersDeobfuscation.printIdentifier(true, ((FullMultinameAVM2Item) spti.propertyName).resolvedMultinameName)); + writer.append(":"); + + type.appendTry(writer, localData); + if (showValue) { + writer.append(" = "); + val.toString(writer, localData); + } + return writer; + } + writer.append("var "); return assignment.toString(writer, localData); } diff --git a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java index 01cf0321f..104812b60 100644 --- a/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java +++ b/libsrc/ffdec_lib/test/com/jpexs/decompiler/flash/as3decompile/ActionScript3AssembledDecompileTest.java @@ -18,7 +18,7 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT @Test public void testActivationProps() { - decompileMethod("assembled", "testActivationProps", "\r\n", + decompileMethod("assembled", "testActivationProps", "var myvar2:int = 10;\r\n", false); } diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc index 0654c160d3afad6bf1b9741a448188d9abd26a81..14763b448d1bfe19c099d0b6c6ba8cdf6d28dce6 100644 GIT binary patch delta 1208 zcmY+DT~HfU6vxlG%kJ4tLcY@k0@@A?C7VE&@D&QRv89B9Z7`*@)LpS!UAz_wKJiisUHJc(lNVqDZ zBxz?!TO_=V)Wyj)S?_m~|0-%}7Jq^aKJC&Yw~%RBCH^F-X>z@ff9U-bJNUfsc=0v{Re+6x4t@_nX~4|Z`ZsENVSwcUB#CJ*--c1z<;c4%xsD;K zEgQxRn9MK_8)m^UpEb-0!|XQ9bG*^NJ39EFFo?pc3aexhmMp8u=l%WBbh4ZlDUX%% zi_{8Qxs&_{|BSM1g|oaZ(3yFvO8y{#R-ua8vT{VPDw_`~av>*WNDVyR+7gJcLx0OE zJIgNz24j7NKFEt)%)zhP_zM3$km=}2UB`;7uh3?44h!SV>?u40dBEd<1WiuGCA*@^ zv%!w0USS*s>{WzeyJL9QHoU}FgLL zh5r&v#f(K>Hbk!7LA`CGUgNRQu=1wmo8gtvMS9Pc=lP!@9rtiwc!)0B$^tKj_k^DZ zd>XP2{=8LI=3j;v#HSo`z}Id63%o6ol{;&lBV)W8$wgH>0SJ(DTsLgj^!mL>1?j3i zIn7(5tJ_pPH>{{I>MZhxwa6KMFIuEqw(VseimeArFyWxC+43C!E%t@zt)+&;$_1;Y z#ve8OO;_yXBER1_j#E4yZ|Y0!oK5AMRaU~($pT^?m2|hFN=E@@I0j6H=RlI7?9gx8 zfEW2(yz9VFa%>26^H4H%7n9{=2Won-8Q`a+uGccHiPnX$%KwF0>!b*i{y(<15(#nY zGY;(?n|6vnj<*fP{zA9-1B|1h!;Dh7C(&So4a@|8}WA|PAy6Jm*kh!`=hFjOqgcdlAI2pla-f_nSa}4y9{|kk1LybwoVQW_^{wF^--`6rSQ} z8Bu(a{pkA`lWfsHIeHg^3cz+D4w?sGDrfcv zyBFw*b{0Az&$+0@X}s|gT4a&^7RaR9lee%W=}XE^Vjc^Fg4tdef;`|kKm~R?6*ugP z66*`5c6V^$0APpA1$!OAO`;d%CFy^cp%Q>d5Twvo$hI&?HN z37CVdWB;mEX0nY?HAv9w7~it>Q!EqCN~ub!{{*Xsa}mO400DB2>b9+#+1v`3kXG#E z0!v4h8%WRf$piyVlSQk^i)<@0N^7?4dA29I8GIH-9II6uzQlfwe#%E{wQ)>-&8jK0 zUmE|ScWv?t`+nEZ*y(w(jF-f~&$XJ?z(>#6F(yHOq#OLIrxOR}68UCDn8M_20Wptq zx?Lvm44?!PAV_c)Lu2BG+S(HJJFLE>;c_8l}LVpiK3oDRSz};e3j7kN?R-* ztA1A0?NE)4^Dv?PP^-n`{AZLMx3_G!Irewc6K%mi&}|)Vf)AcC)v{A;;d9br&B+Dl RPF}IT?}f9C&2xV4@-M*e2o?YU diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestActivationProps.class.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestActivationProps.class.asasm index f2e11ef7d..0a328bc06 100644 --- a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestActivationProps.class.asasm +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestActivationProps.class.asasm @@ -41,6 +41,10 @@ class slotid 1 type QName(PackageNamespace(""),"int") end ; trait + trait slot QName(PackageInternalNs("testing"),"myvar2") + slotid 2 + type QName(PackageNamespace(""),"int") + end ; trait code debug 1, "myvar", 0, 0 getlocal0 @@ -52,6 +56,9 @@ class findpropstrict QName(PackageInternalNs("testing"),"myvar") getlocal1 setproperty QName(PackageInternalNs("testing"),"myvar") + findpropstrict QName(PackageInternalNs("testing"),"myvar2") + pushbyte 10 + setproperty QName(PackageInternalNs("testing"),"myvar2") returnvoid end ; code end ; body diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf b/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf index 8025de6d453db8325b3ee94e29dc042bb8e77e6d..3c7b02db7296a1f9b942127c80f52b632217288e 100644 GIT binary patch literal 4378 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