mirror of
https://git.huckle.dev/Huckles-Minecraft-Archive/jpexs-decompiler.git
synced 2026-07-05 06:34:24 +00:00
@@ -46,6 +46,7 @@ All notable changes to this project will be documented in this file.
|
||||
- [#2493] Incorrect placement of §§push instructions
|
||||
- AS3 direct editation/highlighter §§pop in class traits
|
||||
- AS direct editation/highlighter §§pop and §§dup can have getmember or call
|
||||
- [#1295], [#116] AS3 dynamic construction via MultinameL
|
||||
|
||||
### Changed
|
||||
- Icon of "Deobfuscation options" menu from pile of pills to medkit
|
||||
@@ -3937,6 +3938,8 @@ Major version of SWF to XML export changed to 2.
|
||||
[#2483]: https://www.free-decompiler.com/flash/issues/2483
|
||||
[#2486]: https://www.free-decompiler.com/flash/issues/2486
|
||||
[#2493]: https://www.free-decompiler.com/flash/issues/2493
|
||||
[#1295]: https://www.free-decompiler.com/flash/issues/1295
|
||||
[#116]: https://www.free-decompiler.com/flash/issues/116
|
||||
[#2476]: https://www.free-decompiler.com/flash/issues/2476
|
||||
[#2404]: https://www.free-decompiler.com/flash/issues/2404
|
||||
[#1418]: https://www.free-decompiler.com/flash/issues/1418
|
||||
@@ -4178,7 +4181,6 @@ Major version of SWF to XML export changed to 2.
|
||||
[#2099]: https://www.free-decompiler.com/flash/issues/2099
|
||||
[#2090]: https://www.free-decompiler.com/flash/issues/2090
|
||||
[#2079]: https://www.free-decompiler.com/flash/issues/2079
|
||||
[#116]: https://www.free-decompiler.com/flash/issues/116
|
||||
[#2097]: https://www.free-decompiler.com/flash/issues/2097
|
||||
[#2098]: https://www.free-decompiler.com/flash/issues/2098
|
||||
[#2093]: https://www.free-decompiler.com/flash/issues/2093
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.jpexs.decompiler.flash.abc.avm2.model.FullMultinameAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.RegExpAvm2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.StringAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.XMLAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.TranslateStack;
|
||||
import com.jpexs.helpers.Reference;
|
||||
@@ -108,7 +109,7 @@ public class ConstructPropIns extends InstructionDefinition {
|
||||
|
||||
if (obj instanceof FindPropertyAVM2Item) {
|
||||
multiname.property = false; //can be type
|
||||
}
|
||||
}
|
||||
stack.push(new ConstructPropAVM2Item(ins, localData.lineStartInstruction, obj, multiname, args, type.getVal(), isStatic.getVal()));
|
||||
}
|
||||
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.model;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetVisitorInterface;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -75,12 +78,45 @@ public class ConstructAVM2Item extends AVM2Item {
|
||||
|| (object instanceof CallStaticAVM2Item)
|
||||
|| (object instanceof CallSuperAVM2Item);
|
||||
|
||||
if (object.getPrecedence() > getPrecedence() || objectIsCall) {
|
||||
writer.append("(");
|
||||
boolean isGetDefinition = false;
|
||||
if (object instanceof GetPropertyAVM2Item) {
|
||||
GetPropertyAVM2Item getProperty = (GetPropertyAVM2Item) object;
|
||||
if (getProperty.propertyName instanceof FullMultinameAVM2Item) {
|
||||
FullMultinameAVM2Item fm = (FullMultinameAVM2Item) getProperty.propertyName;
|
||||
if (fm.multinameIndex > 0) {
|
||||
Multiname m = localData.abc.constants.getMultiname(fm.multinameIndex);
|
||||
if (m.kind == Multiname.MULTINAMEL) {
|
||||
if (m.getNamespaceSet(localData.abc.constants).namespaces.length == 1) {
|
||||
isGetDefinition = true;
|
||||
writer.append("(");
|
||||
if (localData.fullyQualifiedNames.contains(DottedChain.parseNoSuffix("flash.utils.getDefinitionByName"))) {
|
||||
writer.append("flash.utils.getDefinitionByName");
|
||||
} else {
|
||||
writer.append("getDefinitionByName");
|
||||
}
|
||||
writer.append("(");
|
||||
String nname = m.getSingleNamespace(localData.abc.constants).getName(localData.abc.constants).toRawString();
|
||||
if (!nname.isEmpty()) {
|
||||
writer.append("\"");
|
||||
writer.append(Helper.escapeActionScriptString(nname));
|
||||
writer.append("\"+\".\"+");
|
||||
}
|
||||
fm.name.appendTo(writer, localData);
|
||||
writer.append("))");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
object.toString(writer, localData);
|
||||
if (object.getPrecedence() > getPrecedence() || objectIsCall) {
|
||||
writer.append(")");
|
||||
|
||||
if (!isGetDefinition) {
|
||||
if (object.getPrecedence() > getPrecedence() || objectIsCall) {
|
||||
writer.append("(");
|
||||
}
|
||||
object.toString(writer, localData);
|
||||
if (object.getPrecedence() > getPrecedence() || objectIsCall) {
|
||||
writer.append(")");
|
||||
}
|
||||
}
|
||||
writer.spaceBeforeCallParenthesis(args.size());
|
||||
if (object instanceof InitVectorAVM2Item) {
|
||||
|
||||
@@ -16,11 +16,14 @@
|
||||
*/
|
||||
package com.jpexs.decompiler.flash.abc.avm2.model;
|
||||
|
||||
import com.jpexs.decompiler.flash.abc.types.Multiname;
|
||||
import com.jpexs.decompiler.flash.helpers.GraphTextWriter;
|
||||
import com.jpexs.decompiler.graph.DottedChain;
|
||||
import com.jpexs.decompiler.graph.GraphSourceItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetItem;
|
||||
import com.jpexs.decompiler.graph.GraphTargetVisitorInterface;
|
||||
import com.jpexs.decompiler.graph.model.LocalData;
|
||||
import com.jpexs.helpers.Helper;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@@ -86,7 +89,36 @@ public class ConstructPropAVM2Item extends AVM2Item {
|
||||
@Override
|
||||
public GraphTextWriter appendTo(GraphTextWriter writer, LocalData localData) throws InterruptedException {
|
||||
writer.append("new ");
|
||||
formatProperty(writer, object, propertyName, localData, isStatic, false);
|
||||
boolean isGetDefinition = false;
|
||||
if (propertyName instanceof FullMultinameAVM2Item) {
|
||||
FullMultinameAVM2Item fm = (FullMultinameAVM2Item) propertyName;
|
||||
if (fm.multinameIndex > 0) {
|
||||
Multiname m = localData.abc.constants.getMultiname(fm.multinameIndex);
|
||||
if (m.kind == Multiname.MULTINAMEL) {
|
||||
if (m.getNamespaceSet(localData.abc.constants).namespaces.length == 1) {
|
||||
isGetDefinition = true;
|
||||
writer.append("(");
|
||||
if (localData.fullyQualifiedNames.contains(DottedChain.parseNoSuffix("flash.utils.getDefinitionByName"))) {
|
||||
writer.append("flash.utils.getDefinitionByName");
|
||||
} else {
|
||||
writer.append("getDefinitionByName");
|
||||
}
|
||||
writer.append("(");
|
||||
String nname = m.getSingleNamespace(localData.abc.constants).getName(localData.abc.constants).toRawString();
|
||||
if (!nname.isEmpty()) {
|
||||
writer.append("\"");
|
||||
writer.append(Helper.escapeActionScriptString(nname));
|
||||
writer.append("\"+\".\"+");
|
||||
}
|
||||
fm.name.appendTo(writer, localData);
|
||||
writer.append("))");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isGetDefinition) {
|
||||
formatProperty(writer, object, propertyName, localData, isStatic, false);
|
||||
}
|
||||
writer.spaceBeforeCallParenthesis(args.size());
|
||||
writer.append("(");
|
||||
for (int a = 0; a < args.size(); a++) {
|
||||
|
||||
@@ -989,7 +989,7 @@ public class Multiname {
|
||||
* @return True if this MULTINAME kind with only one namespace
|
||||
*/
|
||||
public boolean isMULTINAMEwithOneNs(AVM2ConstantPool pool) {
|
||||
return kind == MULTINAME && pool.getNamespaceSet(namespace_set_index).namespaces.length == 1;
|
||||
return (kind == MULTINAME || kind == MULTINAMEL || kind == MULTINAMELA) && pool.getNamespaceSet(namespace_set_index).namespaces.length == 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,10 +21,13 @@ import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.AVM2Deobfuscation;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.AVM2Instruction;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.alchemy.AlchemyTypeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.ConstructPropIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewClassIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.construction.NewFunctionIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetLexIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetOuterScopeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.other.GetPropertyIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.instructions.stack.PushScopeIns;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.model.InitVectorAVM2Item;
|
||||
import com.jpexs.decompiler.flash.abc.avm2.parser.script.AbcIndexing;
|
||||
@@ -196,6 +199,7 @@ public class DependencyParser {
|
||||
}
|
||||
}
|
||||
boolean wasNewClass = false;
|
||||
AVM2Instruction prevIns = null;
|
||||
for (int i = 0; i < body.getCode().code.size(); i++) {
|
||||
AVM2Instruction ins = body.getCode().code.get(i);
|
||||
|
||||
@@ -245,6 +249,26 @@ public class DependencyParser {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ins.definition instanceof ConstructPropIns) {
|
||||
Multiname m = abc.constants.getMultiname(ins.operands[0]);
|
||||
if (m != null) {
|
||||
if (m.kind == Multiname.MULTINAMEL) {
|
||||
Dependency dep = new Dependency(DottedChain.parseNoSuffix("flash.utils.getDefinitionByName"), DependencyType.NAMESPACE);
|
||||
dependencies.add(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: what if there's jump between getproperty and construct?
|
||||
if (ins.definition instanceof ConstructIns && prevIns != null && prevIns.definition instanceof GetPropertyIns) {
|
||||
Multiname m = abc.constants.getMultiname(prevIns.operands[0]);
|
||||
if (m != null) {
|
||||
if (m.kind == Multiname.MULTINAMEL) {
|
||||
Dependency dep = new Dependency(DottedChain.parseNoSuffix("flash.utils.getDefinitionByName"), DependencyType.NAMESPACE);
|
||||
dependencies.add(dep);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (classIndex > -1 && ins.definition instanceof GetOuterScopeIns) {
|
||||
if (ins.operands[0] > 0) { //first is global
|
||||
DottedChain type = abc.instance_info.get(classIndex).getName(abc.constants).getNameWithNamespace(abc.constants, true);
|
||||
@@ -282,6 +306,7 @@ public class DependencyParser {
|
||||
numberContextRef.setVal(ins.operands[k]);
|
||||
}
|
||||
}
|
||||
prevIns = ins;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -748,4 +748,25 @@ public class ActionScript3ClassTest extends ActionScript3DecompileTestBase {
|
||||
+ "}\n"
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConstructDynamically() {
|
||||
decompileScriptPack("assembled", "tests.TestConstructDynamically", "package tests\n"
|
||||
+ "{\n"
|
||||
+ "import flash.display.*;\n"
|
||||
+ "import flash.utils.getDefinitionByName;\n"
|
||||
+ "public class TestConstructDynamically\n"
|
||||
+ "{\n"
|
||||
+ "public function TestConstructDynamically()\n"
|
||||
+ "{\n"
|
||||
+ "super();\n"
|
||||
+ "}\n"
|
||||
+ "public function test() : void\n"
|
||||
+ "{\n"
|
||||
+ "var _loc1_:* = new (getDefinitionByName(\"flash.display\"+\".\"+\"Sprite\"))();\n"
|
||||
+ "_loc1_ = new (getDefinitionByName(\"Object\"))();\n"
|
||||
+ "}\n"
|
||||
+ "}\n"
|
||||
+ "}");
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -40,5 +40,6 @@ program
|
||||
#include "tests/TestAlwaysBreak.script.asasm"
|
||||
#include "tests/TestAlwaysBreak2.script.asasm"
|
||||
#include "tests/TestPushPlacement.script.asasm"
|
||||
#include "tests/TestConstructDynamically.script.asasm"
|
||||
; place to add next
|
||||
end ; program
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
class
|
||||
refid "tests:TestConstructDynamically"
|
||||
instance QName(PackageNamespace("tests"), "TestConstructDynamically")
|
||||
extends QName(PackageNamespace(""), "Object")
|
||||
flag SEALED
|
||||
flag PROTECTEDNS
|
||||
protectedns ProtectedNamespace("tests:TestConstructDynamically")
|
||||
iinit
|
||||
refid "tests:TestConstructDynamically/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(""), "test")
|
||||
method
|
||||
refid "tests:TestConstructDynamically/instance/test"
|
||||
returns QName(PackageNamespace(""), "void")
|
||||
body
|
||||
maxstack 2
|
||||
localcount 4
|
||||
initscopedepth 4
|
||||
maxscopedepth 5
|
||||
code
|
||||
getlocal0
|
||||
pushscope
|
||||
pushstring "Sprite"
|
||||
findpropstrict MultinameL([PackageNamespace("flash.display")])
|
||||
pushstring "Sprite"
|
||||
constructprop MultinameL([PackageNamespace("flash.display")]), 0
|
||||
setlocal1
|
||||
pushstring "Object"
|
||||
findpropstrict MultinameL([PackageNamespace("")])
|
||||
pushstring "Object"
|
||||
getproperty MultinameL([PackageNamespace("")])
|
||||
construct 0
|
||||
setlocal1
|
||||
returnvoid
|
||||
end ; code
|
||||
end ; body
|
||||
end ; method
|
||||
end ; trait
|
||||
end ; instance
|
||||
cinit
|
||||
refid "tests:TestConstructDynamically/class/init"
|
||||
body
|
||||
maxstack 1
|
||||
localcount 1
|
||||
initscopedepth 3
|
||||
maxscopedepth 4
|
||||
code
|
||||
getlocal0
|
||||
pushscope
|
||||
|
||||
returnvoid
|
||||
end ; code
|
||||
end ; body
|
||||
end ; method
|
||||
end ; class
|
||||
@@ -0,0 +1,29 @@
|
||||
script
|
||||
sinit
|
||||
refid "tests:TestConstructDynamically/init"
|
||||
body
|
||||
maxstack 2
|
||||
localcount 1
|
||||
initscopedepth 1
|
||||
maxscopedepth 3
|
||||
code
|
||||
getlocal0
|
||||
pushscope
|
||||
|
||||
findpropstrict Multiname("TestConstructDynamically", [PackageNamespace("tests")])
|
||||
getlex QName(PackageNamespace(""), "Object")
|
||||
pushscope
|
||||
|
||||
getlex Multiname("Object", [PrivateNamespace(null, "tests:TestConstructDynamically"), PackageNamespace(""), PackageNamespace("tests"), PackageInternalNs("tests"), Namespace("http://adobe.com/AS3/2006/builtin")])
|
||||
newclass "tests:TestConstructDynamically"
|
||||
popscope
|
||||
initproperty QName(PackageNamespace("tests"), "TestConstructDynamically")
|
||||
|
||||
returnvoid
|
||||
end ; code
|
||||
end ; body
|
||||
end ; method
|
||||
trait class QName(PackageNamespace("tests"), "TestConstructDynamically")
|
||||
#include "TestConstructDynamically.class.asasm"
|
||||
end ; trait
|
||||
end ; script
|
||||
Binary file not shown.
Reference in New Issue
Block a user