as3 execution fixes

This commit is contained in:
zavarkog
2015-11-18 10:33:13 +01:00
parent c41f9afd0f
commit e9072207c1
63 changed files with 661 additions and 495 deletions

View File

@@ -16,18 +16,16 @@
*/
package com.jpexs.decompiler.flash.gui;
import com.jpexs.decompiler.flash.SWF;
import com.jpexs.decompiler.flash.abc.ABC;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Code;
import com.jpexs.decompiler.flash.abc.avm2.AVM2Runtime;
import com.jpexs.decompiler.flash.abc.avm2.AVM2RuntimeInfo;
import com.jpexs.decompiler.flash.abc.avm2.exceptions.AVM2ExecutionException;
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.IfTypeIns;
import com.jpexs.decompiler.flash.abc.avm2.instructions.InstructionDefinition;
import com.jpexs.decompiler.flash.abc.types.MethodBody;
import com.jpexs.decompiler.flash.action.Action;
import com.jpexs.decompiler.flash.action.ActionList;
import com.jpexs.decompiler.flash.action.ActionLocalData;
import com.jpexs.decompiler.flash.action.LocalDataArea;
import com.jpexs.decompiler.flash.action.swf4.ActionAdd;
@@ -74,33 +72,20 @@ import com.jpexs.decompiler.flash.action.swf6.ActionStringGreater;
import com.jpexs.decompiler.flash.ecma.EcmaScript;
import com.jpexs.decompiler.flash.ecma.Null;
import com.jpexs.decompiler.flash.ecma.Undefined;
import com.jpexs.decompiler.flash.tags.DoABC2Tag;
import com.jpexs.decompiler.flash.tags.Tag;
import com.jpexs.decompiler.flash.tags.base.ASMSource;
import com.jpexs.decompiler.graph.Graph;
import com.jpexs.decompiler.graph.GraphTargetItem;
import com.jpexs.decompiler.graph.TranslateStack;
import com.jpexs.javactivex.ActiveX;
import com.jpexs.javactivex.ActiveXEvent;
import com.jpexs.javactivex.ActiveXEventListener;
import com.jpexs.javactivex.Reference;
import com.jpexs.javactivex.example.controls.flash.ShockwaveFlash;
import java.awt.Panel;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import com.jpexs.helpers.Helper;
import com.jpexs.helpers.utf8.Utf8Helper;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import org.testng.Assert;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.testng.annotations.Test;
/**
*
@@ -108,70 +93,67 @@ import static org.testng.Assert.fail;
*/
public class FlashPlayerTest {
private final Object lockObj = new Object();
private final Random random = new Random();
private final AVM2RuntimeInfo adobeRuntime = new AVM2RuntimeInfo(AVM2Runtime.ADOBE_FLASH, 19, false);
//@Test
public void test1() throws IOException, InterruptedException {
final Reference<String> resultRef = new Reference<>(null);
public void testAs3Pushes() throws IOException, InterruptedException {
AdobeFlashExecutor adobeExecutor = new AdobeFlashExecutor();
ShockwaveFlash flash = ActiveX.createObject(ShockwaveFlash.class, new Panel());
flash.setAllowScriptAccess("always");
flash.setAllowNetworking("all");
flash.addFSCommandListener(new ActiveXEventListener() {
adobeExecutor.loadTestSwf();
ABC abc = adobeExecutor.as3TestSwfAbcTag.getABC();
abc.constants.ensureStringCapacity(1000000);
abc.constants.ensureMultinameCapacity(1000000);
AVM2Instruction[] pushes = getAs3Pushes(abc);
@Override
public void onEvent(ActiveXEvent axe) {
resultRef.setVal((String) axe.args.get("args"));
synchronized (lockObj) {
lockObj.notify();
}
List<AS3ExecuteTask> tasks = new ArrayList<>();
for (int p1 = 0; p1 < pushes.length; p1++) {
AVM2Code ccode = new AVM2Code();
ccode.code = new ArrayList<>();
List<AVM2Instruction> code = ccode.code;
code.add(new AVM2Instruction(0, AVM2Instructions.GetLocal0, null));
code.add(new AVM2Instruction(0, AVM2Instructions.PushScope, null));
code.add(pushes[p1].clone());
code.add(new AVM2Instruction(0, AVM2Instructions.ReturnValue, null));
ccode.markOffsets();
AS3ExecuteTask task = new AS3ExecuteTask();
task.description = p1 + ", " + pushes[p1].definition.instructionName;
task.code = ccode;
String ffdecExecuteResult;
try {
Object res = ccode.execute(new HashMap<>(), abc.constants, adobeRuntime);
ffdecExecuteResult = "Result:" + EcmaScript.toString(res) + " Type:" + EcmaScript.typeString(res);
} catch (AVM2ExecutionException ex) {
ffdecExecuteResult = "Error:" + ex.getMessage();
}
});
File f = new File("libsrc/ffdec_lib/testdata/run_as3/run.swf");
SWF swf = new SWF(new BufferedInputStream(new FileInputStream(f)), false);
swf.version = SWF.MAX_VERSION;
DoABC2Tag abcTag = null;
for (Tag t : swf.tags) {
if (t instanceof DoABC2Tag) {
abcTag = ((DoABC2Tag) t);
break;
}
task.ffdecResult = ffdecExecuteResult;
tasks.add(task);
}
ABC abc = abcTag.getABC();
abc.constants.addUInt(0);
abc.constants.addUInt(100);
abc.constants.addDouble(0.0);
abc.constants.addDouble(111.11);
MethodBody body = abc.findBodyByClassAndName("Run", "run");
body.max_stack = 20;
body.max_regs = 10;
adobeExecutor.executeAvm2(tasks);
for (AS3ExecuteTask task : tasks) {
System.out.println("Flash result (" + task.description + "): " + task.flashResult);
System.out.println("FFDec execte result: " + task.ffdecResult);
assertEquals(task.ffdecResult, task.flashResult);
}
}
AVM2Instruction[] pushes = new AVM2Instruction[]{
new AVM2Instruction(0, AVM2Instructions.PushUndefined, null),
new AVM2Instruction(0, AVM2Instructions.PushNull, null),
new AVM2Instruction(0, AVM2Instructions.PushTrue, null),
new AVM2Instruction(0, AVM2Instructions.PushFalse, null),
new AVM2Instruction(0, AVM2Instructions.PushNan, null),
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{1}),
new AVM2Instruction(0, AVM2Instructions.PushDouble, new int[]{1}),
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{1}),
new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{1}),
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{1}),
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{-2}),
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{-1}),
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{0}),
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{1}),
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{2}),};
@Test
public void testAs3() throws IOException, InterruptedException {
AdobeFlashExecutor adobeExecutor = new AdobeFlashExecutor();
for (int i = 58; i < 256; i++) {
for (int i = 0; i < 256; i++) {
System.out.println("Instruction code: " + Integer.toHexString(i) + " (" + i + ")");
List<AS3ExecuteTask> tasks = new ArrayList<>();
adobeExecutor.loadTestSwf();
ABC abc = adobeExecutor.as3TestSwfAbcTag.getABC();
AVM2Instruction[] pushes = getAs3Pushes(abc);
for (int p1 = 0; p1 < pushes.length; p1++) {
for (int p2 = 0; p2 < pushes.length; p2++) {
System.out.println("p1: " + p1 + " p2: " + p2);
// todo: the following instructions are not implemented
if (i == AVM2Instructions.GetSuper
|| i == AVM2Instructions.SetSuper
@@ -231,11 +213,6 @@ public class FlashPlayerTest {
continue;
}
System.out.println("Instruction code: " + Integer.toHexString(i) + " (" + i + ") " + AVM2Code.instructionSet[i].instructionName);
int j = 1;
File f2 = new File("run_test_" + new Date().getTime() + "_" + i + "_" + j + ".swf");
f2.deleteOnExit();
AVM2Code ccode = new AVM2Code();
ccode.code = new ArrayList<>();
List<AVM2Instruction> code = ccode.code;
@@ -276,225 +253,349 @@ public class FlashPlayerTest {
code.add(new AVM2Instruction(0, AVM2Instructions.TypeOf, null));
code.add(new AVM2Instruction(0, AVM2Instructions.Add, null));
code.add(new AVM2Instruction(0, AVM2Instructions.ReturnValue, null));
ccode.markOffsets();
body.setCode(ccode);
body.markOffsets();
//String pcode = ccode.toASMSource();
//String as = body.toSource();
abcTag.setModified(true);
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(f2))) {
swf.saveTo(fos);
}
flash.setMovie(f2.getAbsolutePath());
synchronized (lockObj) {
lockObj.wait();
}
f2.delete();
String flashResult = resultRef.getVal();
System.out.println("Flash result: " + flashResult);
AS3ExecuteTask task = new AS3ExecuteTask();
task.description = "Instruction code: " + Integer.toHexString(i) + " (" + i + ") " + AVM2Code.instructionSet[i].instructionName + ", "
+ "p1: " + p1 + ", " + pushes[p1].definition.instructionName + ", "
+ "p2: " + p2 + ", " + pushes[p2].definition.instructionName;
task.code = ccode;
String ffdecExecuteResult;
try {
Object res = ccode.execute(new HashMap<>(), abc.constants, AVM2Runtime.ADOBE_FLASH, 19);
Object res = ccode.execute(new HashMap<>(), abc.constants, adobeRuntime);
ffdecExecuteResult = "Result:" + EcmaScript.toString(res) + " Type:" + EcmaScript.typeString(res);
} catch (AVM2ExecutionException ex) {
ffdecExecuteResult = "Error:" + ex.getMessage();
}
System.out.println("FFDec execte result: " + ffdecExecuteResult);
task.ffdecResult = ffdecExecuteResult;
tasks.add(task);
}
}
Assert.assertEquals(ffdecExecuteResult, flashResult);
adobeExecutor.executeAvm2(tasks);
StringBuilder expeced = new StringBuilder();
StringBuilder current = new StringBuilder();
for (AS3ExecuteTask task : tasks) {
/*System.out.println("Flash result (" + task.description + "): " + task.flashResult);
System.out.println("FFDec execte result: " + task.ffdecResult);
if (!task.ffdecResult.equals(task.flashResult)) {
String ffdecExecuteResult;
try {
Object res = task.code.execute(new HashMap<>(), abc.constants, adobeRuntime);
ffdecExecuteResult = "Result:" + EcmaScript.toString(res) + " Type:" + EcmaScript.typeString(res);
} catch (AVM2ExecutionException ex) {
ffdecExecuteResult = "Error:" + ex.getMessage();
}
}
assertEquals(task.ffdecResult, task.flashResult);*/
expeced.append(task.flashResult).append(Helper.newLine);
current.append(task.ffdecResult).append(Helper.newLine);
}
Helper.writeFile("c:\\1\\expected\\" + i + ".txt", Utf8Helper.getBytes(expeced.toString()));
Helper.writeFile("c:\\1\\current\\" + i + ".txt", Utf8Helper.getBytes(current.toString()));
}
}
private AVM2Instruction[] getAs3Pushes(ABC abc) {
AVM2Instruction[] pushes = new AVM2Instruction[]{
new AVM2Instruction(0, AVM2Instructions.PushUndefined, null), // 0
new AVM2Instruction(0, AVM2Instructions.PushNull, null), // 1
new AVM2Instruction(0, AVM2Instructions.PushTrue, null), // 2
new AVM2Instruction(0, AVM2Instructions.PushFalse, null), // 3
new AVM2Instruction(0, AVM2Instructions.PushNan, null), // 4
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{0}), // 5
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("", true)}), // 6
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("-2147483649", true)}), // 7
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("-2147483648", true)}), // 8
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("-2147483647", true)}), // 9
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("-1", true)}), // 10
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("0", true)}), // 11
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("1", true)}), // 12
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("2147483647", true)}), // 13
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("2147483648", true)}), // 14
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("4294967295", true)}), // 15
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("4294967296", true)}), // 16
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("1test", true)}), // 17
new AVM2Instruction(0, AVM2Instructions.PushString, new int[]{abc.constants.getStringId("test", true)}), // 18
new AVM2Instruction(0, AVM2Instructions.PushDouble, new int[]{0}), // 19
new AVM2Instruction(0, AVM2Instructions.PushDouble, new int[]{abc.constants.getDoubleId(-1, true)}), // 20
new AVM2Instruction(0, AVM2Instructions.PushDouble, new int[]{abc.constants.getDoubleId(-0.5, true)}), // 21
new AVM2Instruction(0, AVM2Instructions.PushDouble, new int[]{abc.constants.getDoubleId(0, true)}), // 22
new AVM2Instruction(0, AVM2Instructions.PushDouble, new int[]{abc.constants.getDoubleId(0.5, true)}), // 23
new AVM2Instruction(0, AVM2Instructions.PushDouble, new int[]{abc.constants.getDoubleId(1, true)}), // 24
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-2147483648}), // 25
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-2147483647}), // 26
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-1073741824}), // 27
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-1073741823}), // 28
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-536870912}), // 29
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-536870911}), // 30
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-268435456}), // 31
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-134217728}), // 32
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-134217727}), // 33
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-67108864}), // 34
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-67108863}), // 35
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-33554432}), // 36
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-33554431}), // 37
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-16777216}), // 38
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-16777215}), // 39
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-8388608}), // 40
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-8388607}), // 41
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-4194304}), // 42
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-4194303}), // 43
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-2097152}), // 44
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-2097151}), // 45
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-1048576}), // 46
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-1048575}), // 47
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-524288}), // 48
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-524287}), // 49
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-262144}), // 50
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-262143}), // 51
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-131072}), // 52
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-131071}), // 53
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-65536}), // 54
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-65535}), // 55
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-32768}), // 56
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-32767}), // 57
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{-1}), // 58
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{0}), // 59
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{1}), // 60
/*new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{127}), // 61
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{128}), // 62
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{255}), // 61
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{256}), // 62
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{511}), // 61
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{512}), // 62
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{1023}), // 61
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{1024}), // 62
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{2047}), // 61
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{2048}), // 62
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{4095}), // 61
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{4096}), // 62
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{8191}), // 61
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{8192}), // 62
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{16383}), // 61
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{16384}), // 62*/
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{32767}), // 61
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{32768}), // 62
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{268435455}), // 63
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{268435456}), // 64
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{536870911}), // 65
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{536870912}), // 66
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{1073741823}), // 67
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{1073741824}), // 68
new AVM2Instruction(0, AVM2Instructions.PushShort, new int[]{2147483647}), // 69
new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{0}), // 70
new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{abc.constants.getIntId(-2147483649L, true)}), // 71
new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{abc.constants.getIntId(-2147483648, true)}), // 72
new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{abc.constants.getIntId(-1, true)}), // 73
new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{abc.constants.getIntId(0, true)}), // 74
new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{abc.constants.getIntId(1, true)}), // 75
new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{abc.constants.getIntId(2147483647, true)}), // 76
new AVM2Instruction(0, AVM2Instructions.PushInt, new int[]{abc.constants.getIntId(2147483648L, true)}), // 77
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getIntId(4294967295L, true)}), // 78
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getIntId(4294967296L, true)}), // 79
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{0}), // 80
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getUIntId(-2147483649L, true)}), // 81
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getUIntId(-2147483648, true)}), // 82
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getUIntId(-1, true)}), // 83
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getUIntId(0, true)}), // 84
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getUIntId(1, true)}), // 85
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getUIntId(2147483647, true)}), // 86
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getUIntId(2147483648L, true)}), // 87
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getUIntId(4294967295L, true)}), // 88
new AVM2Instruction(0, AVM2Instructions.PushUInt, new int[]{abc.constants.getUIntId(4294967296L, true)}), // 89
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{-2147483648}), // 90
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{-256}), // 91
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{-255}), // 92
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{-128}), // 93
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{-127}), // 94
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{-2}), // 95
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{-1}), // 96
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{0}), // 97
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{1}), // 98
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{2}), // 99
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{127}), // 100
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{128}), // 101
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{255}), // 102
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{256}), // 103
new AVM2Instruction(0, AVM2Instructions.PushByte, new int[]{2147483647}),}; // 104
return pushes;
}
//@Test
public void testAs2() throws InterruptedException {
AdobeFlashExecutor adobeExecutor = new AdobeFlashExecutor();
List<AS2ExecuteTask> tasks = new ArrayList<>();
Object[] pushes = getAs2Pushes();
for (int i = 0; i < 13 + 23 + 2; i++) {
for (int p1 = 0; p1 < 15; p1++) {
int p2Count = 1;
if (i >= 13) {
p2Count = pushes.length;
}
for (int p2 = 0; p2 < p2Count; p2++) {
List<Action> newActions = new ArrayList<>();
Action opAction = getOpAction(i);
if (i >= 13 + 23) {
newActions.add(new ActionPush("mystring_árvíztűrő_tükörfúrógép"));
}
Object p1o = pushes[p1];
Object p2o = null;
if (i >= 13) {
p2o = pushes[p2];
newActions.add(new ActionPush(p2o));
}
newActions.add(new ActionPush(p1o));
newActions.add(opAction);
newActions.add(new ActionPushDuplicate());
newActions.add(new ActionTypeOf());
newActions.add(new ActionStackSwap());
newActions.add(new ActionStringAdd());
AS2ExecuteTask task = new AS2ExecuteTask();
task.description = i + " " + opAction.toString() + " p1:" + p1o + " p2:" + p2o + " r3:" + "mystring";
task.actions = newActions;
List<GraphTargetItem> output = new ArrayList<>();
ActionLocalData localData = new ActionLocalData();
TranslateStack stack = new TranslateStack("");
for (Action a : newActions) {
a.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
}
String ffdecTranslateResult;
try {
Object res = stack.pop().getResult();
ffdecTranslateResult = "Result:" + EcmaScript.toString(res) + " Type:" + EcmaScript.typeString(res);
} catch (Exception e) {
ffdecTranslateResult = "Error:" + e.getMessage();
}
String ffdecExecuteResult;
try {
LocalDataArea lda = new LocalDataArea();
for (Action a : newActions) {
if (!a.execute(lda)) {
fail();
}
}
Object res = lda.stack.pop();
ffdecExecuteResult = "Result:" + EcmaScript.toString(res) + " Type:" + EcmaScript.typeString(res);
} catch (Exception e) {
ffdecExecuteResult = "Error:" + e.getMessage();
}
assertEquals(ffdecTranslateResult, ffdecExecuteResult);
task.ffdecResult = ffdecExecuteResult;
tasks.add(task);
}
}
}
/*int cnt = 0;
while (flash.getReadyState() != 4) {
Thread.sleep(50);
if (cnt > 100) {
Assert.fail("Flash init timeout");
}
adobeExecutor.executeActionLists(tasks);
cnt++;
}*/
/*try {
String res = flash.CallFunction("<invoke name=\"testFunc\" returntype=\"xml\"><arguments><string>something</string></arguments></invoke>");
//String str = flash.GetVariable("_root.myText.text");
throw new Error(res + " " + body.getCode().toString() + "");
} catch (Exception ex) {
int a = 1;
}*/
}
StringBuilder expeced = new StringBuilder();
StringBuilder current = new StringBuilder();
for (AS2ExecuteTask task : tasks) {
System.out.println(task.description);
String flashResult = task.flashResult;
String ffdecResult = task.ffdecResult;
System.out.println("FFDec result: " + ffdecResult);
//@Test
public void testAs2() throws IOException, InterruptedException {
final Reference<String> resultRef = new Reference<>(null);
boolean checkOnlyStart = false;
/*if (flashResult.length() > 10) {
boolean onlyNumber = true;
for (int k = 0; k < 10; k++) {
char ch = flashResult.charAt(flashResult.length() - k - 1);
if (ch < '0' || ch > '9') {
onlyNumber = false;
break;
}
}
ShockwaveFlash flash = ActiveX.createObject(ShockwaveFlash.class, new Panel());
flash.setAllowScriptAccess("always");
flash.setAllowNetworking("all");
flash.addFSCommandListener(new ActiveXEventListener() {
if (onlyNumber) {
flashResult = flashResult.substring(0, flashResult.length() - 1);
checkOnlyStart = true;
}
}*/
@Override
public void onEvent(ActiveXEvent axe) {
resultRef.setVal((String) axe.args.get("args"));
synchronized (lockObj) {
lockObj.notify();
}
if (flashResult.equals("Result:number-0.00390625000090949 Type:string")) {
flashResult = "Result:number-0.0039062500009095 Type:string";
} else if (flashResult.equals("Result:number-0.0000610349234335671 Type:string")) {
flashResult = "Result:number-0.0000610349234335672 Type:string";
}
});
File f = new File("libsrc/ffdec_lib/testdata/run_as2/run_as2.swf");
for (int i = 0; i < 15; i++) {
for (int j = 0; j < 13 + 23 + 2; j++) {
File f2 = new File("run_test_" + new Date().getTime() + "_" + i + "_" + j + ".swf");
f2.deleteOnExit();
SWF swf = new SWF(new BufferedInputStream(new FileInputStream(f)), false);
Map<String, ASMSource> asms = swf.getASMs(true);
ASMSource asm = asms.get("\\frame_1\\DoAction");
ActionList actions = asm.getActions();
actions.removeAction(2, 4);
List<Action> newActions = new ArrayList<>();
int r1 = random.nextInt(500) - 255;
int r2 = random.nextInt(100);
Action opAction = getOpAction(j);
if (j >= 13 + 23) {
newActions.add(new ActionPush("mystring_árvíztűrő_tükörfúrógép"));
}
if (j >= 13) {
newActions.add(new ActionPush(r1));
}
Object r2Obj;
if (i == 0) {
r2Obj = Undefined.INSTANCE;
} else if (i == 1) {
r2Obj = Null.INSTANCE;
} else if (i == 2) {
r2Obj = false;
} else if (i == 3) {
r2Obj = true;
} else if (i == 4) {
r2Obj = "";
} else if (i == 5) {
r2Obj = "test";
} else if (i == 6) {
r2Obj = "0";
} else if (i == 7) {
r2Obj = "0.0";
} else if (i == 8) {
r2Obj = "1.0";
} else if (i == 9) {
r2Obj = "-1.0";
} else if (i == 10) {
r2Obj = 0;
} else if (i == 11) {
r2Obj = -100;
} else if (i == 12) {
r2Obj = 100;
} else {
r2Obj = r2;
}
newActions.add(new ActionPush(r2Obj));
System.out.println(i + " " + j + " " + opAction.toString() + " r1:" + r1 + " r2:" + r2Obj + " r3:" + "mystring");
newActions.add(opAction);
newActions.add(new ActionPushDuplicate());
newActions.add(new ActionTypeOf());
newActions.add(new ActionStackSwap());
newActions.add(new ActionStringAdd());
actions.addActions(2, newActions);
List<GraphTargetItem> output = new ArrayList<>();
ActionLocalData localData = new ActionLocalData();
TranslateStack stack = new TranslateStack("");
for (Action a : newActions) {
a.translate(localData, stack, output, Graph.SOP_USE_STATIC, "");
}
Object ffdecResult = stack.pop().getResult();
System.out.println("FFDec result: " + ffdecResult);
if (!ffdecResult.equals(flashResult)) {
LocalDataArea lda = new LocalDataArea();
for (Action a : newActions) {
for (Action a : task.actions) {
if (!a.execute(lda)) {
fail();
}
}
Object ffdecExecuteResult = lda.stack.pop();
System.out.println("FFDec execte result: " + ffdecExecuteResult);
asm.setActions(actions);
asm.setModified();
try (OutputStream fos = new BufferedOutputStream(new FileOutputStream(f2))) {
swf.saveTo(fos);
}
flash.setMovie(f2.getAbsolutePath());
synchronized (lockObj) {
lockObj.wait();
}
String str = flash.GetVariable("myText.text");
String flashResult = resultRef.getVal();
boolean checkOnlyStart = false;
/*if (flashResult.length() > 10) {
boolean onlyNumber = true;
for (int k = 0; k < 10; k++) {
char ch = flashResult.charAt(flashResult.length() - k - 1);
if (ch < '0' || ch > '9') {
onlyNumber = false;
break;
}
}
if (onlyNumber) {
flashResult = flashResult.substring(0, flashResult.length() - 1);
checkOnlyStart = true;
}
}*/
if (checkOnlyStart) {
Assert.assertTrue(((String) ffdecResult).startsWith(flashResult));
Assert.assertTrue(((String) ffdecExecuteResult).startsWith(flashResult));
} else {
Assert.assertEquals(ffdecResult, flashResult);
Assert.assertEquals(ffdecExecuteResult, flashResult);
}
f2.delete();
Object res = lda.stack.pop();
}
if (checkOnlyStart) {
assertTrue(((String) ffdecResult).startsWith(flashResult));
} else {
assertEquals(ffdecResult, flashResult);
}
expeced.append(task.description).append(task.flashResult).append(Helper.newLine);
current.append(task.description).append(task.ffdecResult).append(Helper.newLine);
}
Helper.writeFile("c:\\1\\expected.txt", Utf8Helper.getBytes(expeced.toString()));
Helper.writeFile("c:\\1\\current.txt", Utf8Helper.getBytes(current.toString()));
}
private Object[] getAs2Pushes() {
int r1 = random.nextInt(500) - 255;
int r2 = random.nextInt(100);
Object[] pushes = new Object[]{
Undefined.INSTANCE, Null.INSTANCE,
false, true,
Double.NaN,
"", "-2147483649", "-2147483648", "-2147483647", "-1", "0", "1", "2147483647", "2147483648", "4294967295", "4294967296", "1test", "test", "0.0", "1.0", "-1.0",
-1.0, -0.5, 0, 0.5, 1.0,
-2147483648, -2147483647, -1073741824, -1073741823, -536870912, -536870911, -268435456, -134217728, -134217727, -67108864, -67108863, -33554432,
-33554431, -16777216, -16777215, -8388608, -8388607, -4194304, -4194303, -2097152, -2097151, -1048576, -1048575, -524288, -524287, -262144, -262143, -131072, -131071, -65536, -65535, -32768, -32767, -1, 0, 1, 32767, 32768, 268435455,
-100, 100,
//r1, r2
-225, 66
};
return pushes;
}
private Action getOpAction(int idx) {
Action result;
if (idx < 13) {
result = getUnaryOpAction(idx);
Assert.assertEquals(1, result.getStackPopCount(null, null));
Assert.assertEquals(1, result.getStackPushCount(null, null));
assertEquals(1, result.getStackPopCount(null, null));
assertEquals(1, result.getStackPushCount(null, null));
} else if (idx < 13 + 23) {
result = getBinaryOpAction(idx - 13);
Assert.assertEquals(2, result.getStackPopCount(null, null));
Assert.assertEquals(1, result.getStackPushCount(null, null));
assertEquals(2, result.getStackPopCount(null, null));
assertEquals(1, result.getStackPushCount(null, null));
} else {
result = getTernaryOpAction(idx - 13 - 23);
Assert.assertEquals(3, result.getStackPopCount(null, null));
Assert.assertEquals(1, result.getStackPushCount(null, null));
assertEquals(3, result.getStackPopCount(null, null));
assertEquals(1, result.getStackPushCount(null, null));
}
return result;