diff --git a/CHANGELOG.md b/CHANGELOG.md index f34019c79..4785aa78b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ All notable changes to this project will be documented in this file. - [#2537] AS1/2/3 direct editation - partial object literal causing lag - [#2540] AS3 getlocal after inclocal with different registers incorrectly merged - [PR224] Font CLI replace throwing NullPointer +- [#2546] AS3 findProperty vs temporary registers ## [24.1.0] - 2025-09-28 ### Added @@ -4023,6 +4024,7 @@ Major version of SWF to XML export changed to 2. [#2536]: https://www.free-decompiler.com/flash/issues/2536 [#2537]: https://www.free-decompiler.com/flash/issues/2537 [#2540]: https://www.free-decompiler.com/flash/issues/2540 +[#2546]: https://www.free-decompiler.com/flash/issues/2546 [#2477]: https://www.free-decompiler.com/flash/issues/2477 [#2478]: https://www.free-decompiler.com/flash/issues/2478 [#2485]: https://www.free-decompiler.com/flash/issues/2485 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 69ad99380..712b4068a 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 @@ -1373,6 +1373,23 @@ public abstract class InstructionDefinition implements Serializable { } } + if (obj instanceof TemporaryItem) { + TemporaryItem temporaryItemObj = (TemporaryItem) obj; + if (temporaryItemObj.value instanceof FindPropertyAVM2Item) { + for (int i = output.size() - 1; i >= 0; i--) { + if (output.get(i) instanceof SetTemporaryItem) { + SetTemporaryItem setTemp = (SetTemporaryItem) output.get(i); + if (setTemp.getTempIndex() == temporaryItemObj.getTempIndex()) { + output.remove(i); + obj = temporaryItemObj.value; + break; + } + } + } + } + } + + Reference isStatic = new Reference<>(false); Reference type = new Reference<>(null); Reference callType = new Reference<>(null); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropVoidIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropVoidIns.java index c54644b8d..a05f7a59f 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropVoidIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropVoidIns.java @@ -25,9 +25,12 @@ 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.other.GetPropertyIns; import com.jpexs.decompiler.flash.abc.avm2.model.CallPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.SetTemporaryItem; +import com.jpexs.decompiler.graph.model.TemporaryItem; import com.jpexs.helpers.Reference; import java.util.ArrayList; import java.util.List; @@ -85,6 +88,23 @@ public class CallPropVoidIns extends InstructionDefinition { FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); + + if (obj instanceof TemporaryItem) { + TemporaryItem temporaryItemObj = (TemporaryItem) obj; + if (temporaryItemObj.value instanceof FindPropertyAVM2Item) { + for (int i = output.size() - 1; i >= 0; i--) { + if (output.get(i) instanceof SetTemporaryItem) { + SetTemporaryItem setTemp = (SetTemporaryItem) output.get(i); + if (setTemp.getTempIndex() == temporaryItemObj.getTempIndex()) { + output.remove(i); + obj = temporaryItemObj.value; + break; + } + } + } + } + } + Reference isStatic = new Reference<>(false); Reference type = new Reference<>(null); Reference callType = new Reference<>(null); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropertyIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropertyIns.java index d522a31bc..fc5103826 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropertyIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/executing/CallPropertyIns.java @@ -25,10 +25,13 @@ 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.other.GetPropertyIns; import com.jpexs.decompiler.flash.abc.avm2.model.CallPropertyAVM2Item; +import com.jpexs.decompiler.flash.abc.avm2.model.FindPropertyAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item; import com.jpexs.decompiler.flash.ecma.NotCompileTime; import com.jpexs.decompiler.graph.GraphTargetItem; import com.jpexs.decompiler.graph.TranslateStack; +import com.jpexs.decompiler.graph.model.SetTemporaryItem; +import com.jpexs.decompiler.graph.model.TemporaryItem; import com.jpexs.helpers.Reference; import java.util.ArrayList; import java.util.List; @@ -85,6 +88,23 @@ public class CallPropertyIns extends InstructionDefinition { FullMultinameAVM2Item multiname = resolveMultiname(localData, true, stack, localData.getConstants(), multinameIndex, ins, output); GraphTargetItem obj = stack.pop(); + + if (obj instanceof TemporaryItem) { + TemporaryItem temporaryItemObj = (TemporaryItem) obj; + if (temporaryItemObj.value instanceof FindPropertyAVM2Item) { + for (int i = output.size() - 1; i >= 0; i--) { + if (output.get(i) instanceof SetTemporaryItem) { + SetTemporaryItem setTemp = (SetTemporaryItem) output.get(i); + if (setTemp.getTempIndex() == temporaryItemObj.getTempIndex()) { + output.remove(i); + obj = temporaryItemObj.value; + break; + } + } + } + } + } + Reference isStatic = new Reference<>(false); Reference type = new Reference<>(null); Reference callType = new Reference<>(null); 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 b7ef968e9..10b7acaf4 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 @@ -92,8 +92,8 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT @Test public void testCollidingPublicTraits() { - decompileMethod("assembled", "testCollidingPublicTraits", "trace(\"ns1 = \" + this.a#89);\r\n" - + "trace(\"ns2 = \" + this.a#90);\r\n", + decompileMethod("assembled", "testCollidingPublicTraits", "trace(\"ns1 = \" + this.a#90);\r\n" + + "trace(\"ns2 = \" + this.a#91);\r\n", false); } @@ -167,6 +167,17 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT false); } + @Test + public void testFindPropertyTemp() { + decompileMethod("assembled", "testFindPropertyTemp", "var _temp_1:* = _loc1_.target;\r\n" + + "_temp_1.method();\r\n" + + "testA = _temp_1;\r\n" + + "var _temp_3:* = _loc9_[_loc2_];\r\n" + + "testB(_temp_3,new (getDefinitionByName(\"Str_\" + _temp_3))().sub);\r\n" + + "_loc2_++;\r\n", + false); + } + @Test public void testForEach() { decompileMethod("assembled", "testForEach", "var _loc5_:* = undefined;\r\n" diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc index 52d7d2259..17f1b2d08 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc and b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.abc differ diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm index 31eebceb2..ffcdba87c 100644 --- a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/as3_assembled-0.main.asasm @@ -43,5 +43,6 @@ program #include "tests/TestConstructDynamically.script.asasm" #include "tests/TestCollidingPublicTraits.script.asasm" #include "tests/TestSetGetLocalOnStack.script.asasm" + #include "tests/TestFindPropertyTemp.script.asasm" ; place to add next end ; program diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestFindPropertyTemp.class.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestFindPropertyTemp.class.asasm new file mode 100644 index 000000000..8397f1c4c --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestFindPropertyTemp.class.asasm @@ -0,0 +1,83 @@ +class + refid "tests:TestFindPropertyTemp" + instance QName(PackageNamespace("tests"), "TestFindPropertyTemp") + extends QName(PackageNamespace(""), "Object") + flag SEALED + flag PROTECTEDNS + protectedns ProtectedNamespace("tests:TestFindPropertyTemp") + iinit + refid "tests:TestFindPropertyTemp/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:TestFindPropertyTemp/instance/run" + returns QName(PackageNamespace(""), "void") + body + maxstack 2 + localcount 4 + initscopedepth 4 + maxscopedepth 5 + code + getlocal0 + pushscope + + findproperty QName(PackageNamespace(""),"testA") + getlocal1 + getproperty QName(PackageNamespace(""),"target") + dup + callpropvoid QName(PackageNamespace(""),"method"), 0 + setproperty QName(PackageNamespace(""),"testA") + findproperty QName(PackageNamespace(""),"testB") + getlocal 9 + getlocal2 + getproperty MultinameL([PackageNamespace("")]) + dup + pushstring "Str_" + swap + add + dup + findproperty MultinameL([PackageNamespace("")]) + swap + getproperty MultinameL([PackageNamespace("")]) + construct 0 + getproperty QName(PackageNamespace(""),"sub") + callpropvoid QName(PackageNamespace(""),"testB"), 2 + inclocal_i 2 + + returnvoid + end ; code + end ; body + end ; method + end ; trait + end ; instance + cinit + refid "tests:TestFindPropertyTemp/class/init" + body + maxstack 1 + localcount 1 + initscopedepth 3 + maxscopedepth 4 + code + getlocal0 + pushscope + + returnvoid + end ; code + end ; body + end ; method +end ; class diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestFindPropertyTemp.script.asasm b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestFindPropertyTemp.script.asasm new file mode 100644 index 000000000..984384f87 --- /dev/null +++ b/libsrc/ffdec_lib/testdata/as3_assembled/abc/as3_assembled-0/tests/TestFindPropertyTemp.script.asasm @@ -0,0 +1,29 @@ +script + sinit + refid "tests:TestFindPropertyTemp/init" + body + maxstack 2 + localcount 1 + initscopedepth 1 + maxscopedepth 3 + code + getlocal0 + pushscope + + findpropstrict Multiname("TestFindPropertyTemp", [PackageNamespace("tests")]) + getlex QName(PackageNamespace(""), "Object") + pushscope + + getlex Multiname("Object", [PrivateNamespace(null, "tests:TestFindPropertyTemp"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")]) + newclass "tests:TestFindPropertyTemp" + popscope + initproperty QName(PackageNamespace("tests"), "TestFindPropertyTemp") + + returnvoid + end ; code + end ; body + end ; method + trait class QName(PackageNamespace("tests"), "TestFindPropertyTemp") + #include "TestFindPropertyTemp.class.asasm" + end ; trait +end ; script diff --git a/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf b/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf index f968761bd..69818499f 100644 Binary files a/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf and b/libsrc/ffdec_lib/testdata/as3_assembled/bin/as3_assembled.swf differ