From d51e75d0e7f75d18b96850d7e50e19a073057932 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jindra=20Pet=C5=99=C3=ADk?= Date: Mon, 1 Sep 2025 09:37:44 +0200 Subject: [PATCH] Simple values are not duplicated with DuplicateItem/SetTemporary. --- .../abc/avm2/instructions/SetTypeIns.java | 38 +++++++++++++++++-- .../abc/avm2/instructions/stack/DupIns.java | 13 ++++++- .../decompiler/graph/GraphTargetItem.java | 33 ++++++++++++++++ .../ActionScript3AssembledDecompileTest.java | 26 ++++++------- 4 files changed, 91 insertions(+), 19 deletions(-) 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 2f8b11c8e..3a7dcf7e6 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 @@ -79,9 +79,37 @@ public interface SetTypeIns { } //TestChainedAssignments1 both AIR and nonair - if (notCoercedValue instanceof DuplicateItem) { + stack.moveToStack(output); + if (!stack.isEmpty()) { + if (GraphTargetItem.checkDup2(notCoercedValue, stack.peek(), output, stack) >= -1) { + GraphTargetItem newValue = notCoercedValue.getThroughDuplicate(); + if ((value instanceof CoerceAVM2Item) || (value instanceof ConvertAVM2Item)) { + result.value.value = newValue; + } else { + result.value = newValue; + } + + //Assembled - TestForEach + if (AVM2Item.mustStayIntact2(newValue) && result instanceof SetLocalAVM2Item) { + SetLocalAVM2Item setLocal = (SetLocalAVM2Item) result; + stack.pop(); + stack.moveToStack(output); + stack.addToOutput(result); + stack.push(new LocalRegAVM2Item(null, null, setLocal.regIndex, setLocal.value, setLocal.type)); + return; + } + + + stack.pop(); + stack.moveToStack(output); + stack.push(result); + return; + } + } + stack.finishBlock(output); + /*if (notCoercedValue instanceof DuplicateItem) { DuplicateItem d = (DuplicateItem) notCoercedValue; - stack.moveToStack(output); + if (!stack.isEmpty() && stack.peek() instanceof DuplicateSourceItem) { DuplicateSourceItem ds = (DuplicateSourceItem) stack.peek(); if (ds.tempIndex == d.tempIndex) { @@ -116,8 +144,10 @@ public interface SetTypeIns { return; } } - stack.finishBlock(output); - } + + }*/ + + stack.addToOutput(result); if (true) { //FIXME?? diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/DupIns.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/DupIns.java index 1f561b22c..c8fa64468 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/DupIns.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/flash/abc/avm2/instructions/stack/DupIns.java @@ -24,9 +24,9 @@ import com.jpexs.decompiler.flash.abc.avm2.graph.AVM2GraphTargetDialect; import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction; import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition; import com.jpexs.decompiler.flash.abc.avm2.model.NewActivationAVM2Item; -import com.jpexs.decompiler.flash.abc.avm2.model.SetTypeAVM2Item; import com.jpexs.decompiler.flash.abc.avm2.model.clauses.ExceptionAVM2Item; import com.jpexs.decompiler.graph.GraphTargetItem; +import com.jpexs.decompiler.graph.SimpleValue; import com.jpexs.decompiler.graph.TranslateStack; import com.jpexs.decompiler.graph.model.DuplicateItem; import com.jpexs.decompiler.graph.model.DuplicateSourceItem; @@ -60,7 +60,16 @@ public class DupIns extends InstructionDefinition { public void translate(AVM2LocalData localData, TranslateStack stack, AVM2Instruction ins, List output, String path) { GraphTargetItem v = stack.pop(); int temp = 0; - + + if (v instanceof SimpleValue) { + SimpleValue sv = (SimpleValue) v; + if (sv.isSimpleValue()) { + stack.push(v); + stack.push(v); + return; + } + } + if (v instanceof NewActivationAVM2Item || v instanceof ExceptionAVM2Item) { stack.push(v); diff --git a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java index 3f03ff554..180af7e4c 100644 --- a/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java +++ b/libsrc/ffdec_lib/src/com/jpexs/decompiler/graph/GraphTargetItem.java @@ -26,6 +26,7 @@ import com.jpexs.decompiler.flash.helpers.hilight.HighlightData; import com.jpexs.decompiler.graph.model.BinaryOp; import com.jpexs.decompiler.graph.model.DuplicateItem; import com.jpexs.decompiler.graph.model.DuplicateSourceItem; +import com.jpexs.decompiler.graph.model.HasTempIndex; import com.jpexs.decompiler.graph.model.LocalData; import com.jpexs.decompiler.graph.model.NotItem; import com.jpexs.decompiler.graph.model.SetTemporaryItem; @@ -1178,4 +1179,36 @@ public abstract class GraphTargetItem implements Serializable, Cloneable { output.remove(output.size() - 1); stack.moveToStack(output); } + + /** + * Checks whether items are result of dup instruction and removes SetTemportary from output when neccessary + * @param item1 + * @param item2 + * @param output + * @param stack + * @return -2 when no duplicate, -1 when equal, >= 0 temp index + */ + public static int checkDup2(GraphTargetItem item1, GraphTargetItem item2, List output, TranslateStack stack) { + if (item1 == item2) { + return -1; + } + if (!((item1 instanceof DuplicateSourceItem && item2 instanceof DuplicateItem) + || (item1 instanceof DuplicateItem && item2 instanceof DuplicateSourceItem)) + ) { + return -2; + } + if (((HasTempIndex) item1).getTempIndex() != ((HasTempIndex) item2).getTempIndex()) { + return -2; + } + + if (!output.isEmpty() && output.get(output.size() - 1) instanceof SetTemporaryItem) { + SetTemporaryItem st = (SetTemporaryItem) output.get(output.size() - 1); + if (st.getTempIndex() == ((HasTempIndex) item1).getTempIndex()) { + output.remove(output.size() - 1); + stack.moveToStack(output); + } + } + + return ((HasTempIndex) item1).getTempIndex(); + } } 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 3adf4bba1..bfae48081 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 @@ -141,10 +141,11 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT false); } - @Test(enabled = false) + @Test public void testDoubleDup() { - decompileMethod("assembled", "testDoubleDup", "var _loc10_:Rectangle = myprop(_loc5_);\r\n" - + "_loc10_.mymethod(-_loc10_.width,-_loc10_.height);\r\n", + decompileMethod("assembled", "testDoubleDup", "var _temp_1:* = myprop(_loc5_);\r\n" + + "var _loc10_:* = _temp_1;\r\n" + + "_temp_1.mymethod(-_temp_1.width,-_loc10_.height);\r\n", false); } @@ -341,23 +342,22 @@ public class ActionScript3AssembledDecompileTest extends ActionScript3DecompileT @Test public void testPushWhile() { decompileMethod("assembled", "testPushWhile", "var _loc3_:int = 5;\r\n" - + "var _temp_1:* = \"ByteArray\";\r\n" - + "§§push(obfuscated[\"xxx\"] = new (getDefinitionByName(\"flash.utils\"+\".\"+_temp_1))());\r\n" + + "§§push(obfuscated[\"xxx\"] = new (getDefinitionByName(\"flash.utils\"+\".\"+\"ByteArray\"))());\r\n" + "§§push(50);\r\n" + "while(true)\r\n" + "{\r\n" - + "var _temp_4:* = §§pop();\r\n" - + "§§push(_temp_4);\r\n" - + "if(!_temp_4)\r\n" + + "var _temp_3:* = §§pop();\r\n" + + "§§push(_temp_3);\r\n" + + "if(!_temp_3)\r\n" + "{\r\n" + "break;\r\n" + "}\r\n" - + "var _temp_5:* = §§pop();\r\n" - + "var _temp_6:* = §§pop() - 1;\r\n" - + "_temp_5[_temp_5.length] = 0x29 ^ 0x6F;\r\n" - + "_temp_5[_temp_5.length] = 9 ^ 0x54;\r\n" + + "var _temp_4:* = §§pop();\r\n" + + "var _temp_5:* = §§pop() - 1;\r\n" + + "_temp_4[_temp_4.length] = 0x29 ^ 0x6F;\r\n" + + "_temp_4[_temp_4.length] = 9 ^ 0x54;\r\n" + + "§§push(_temp_4);\r\n" + "§§push(_temp_5);\r\n" - + "§§push(_temp_6);\r\n" + "}\r\n" + "§§pop();\r\n" + "§§pop();\r\n",