internal virtual void init(int p1, ActionList p2, ConstantPool p3, String p4, DefineFunction p5) { at = p1; actions = p2; pool = p3; className = p4; function = p5; }
public override void defineFunction2(DefineFunction action) { start(action); out_Renamed.Write(" " + action.name + "("); for (int i = 0; i < action.params_Renamed.Length; i++) { out_Renamed.Write("$" + action.paramReg[i] + "=" + action.params_Renamed[i]); if (i + 1 < action.params_Renamed.Length) { out_Renamed.Write(", "); } } out_Renamed.Write(")"); int regno = 1; if ((action.flags & DefineFunction.kPreloadThis) != 0) { out_Renamed.Write(" $" + (regno++) + "=this"); } if ((action.flags & DefineFunction.kPreloadArguments) != 0) { out_Renamed.Write(" $" + (regno++) + "=arguments"); } if ((action.flags & DefineFunction.kPreloadSuper) != 0) { out_Renamed.Write(" $" + (regno++) + "=super"); } if ((action.flags & DefineFunction.kPreloadRoot) != 0) { out_Renamed.Write(" $" + (regno++) + "=_root"); } if ((action.flags & DefineFunction.kPreloadParent) != 0) { out_Renamed.Write(" $" + (regno++) + "=_parent"); } if ((action.flags & DefineFunction.kPreloadGlobal) != 0) { out_Renamed.Write(" $" + (regno) + "=_global"); } out_Renamed.WriteLine(" {"); indent_Renamed_Field++; action.actionList.visitAll(this); indent_Renamed_Field--; indent(); out_Renamed.WriteLine("} " + action.name); }
public override void defineFunction(DefineFunction action) { start(action); out_Renamed.Write(" " + action.name + "("); for (int i = 0; i < action.params_Renamed.Length; i++) { out_Renamed.Write(action.params_Renamed[i]); if (i + 1 < action.params_Renamed.Length) { out_Renamed.Write(", "); } } out_Renamed.WriteLine(") {"); indent_Renamed_Field++; action.actionList.visitAll(this); indent_Renamed_Field--; indent(); out_Renamed.WriteLine("} " + action.name); }
public static InstructionCollection Parse(Stream input, long instructionsPosition) { var instructions = new SortedList <int, InstructionBase>(); using (var helper = new InstructionParseHelper(input, instructionsPosition)) { var reader = helper.GetReader(); while (helper.CanParse(instructions)) { //now reader the instructions var instructionPosition = helper.CurrentPosition; var type = reader.ReadByteAsEnum <InstructionType>(); var requireAlignment = InstructionAlignment.IsAligned(type); if (requireAlignment) { reader.Align(4); } InstructionBase instruction = null; var parameters = new List <Value>(); switch (type) { case InstructionType.ToNumber: instruction = new ToNumber(); break; case InstructionType.NextFrame: instruction = new NextFrame(); break; case InstructionType.Play: instruction = new Play(); break; case InstructionType.Stop: instruction = new Stop(); break; case InstructionType.Add: instruction = new Add(); break; case InstructionType.Subtract: instruction = new Subtract(); break; case InstructionType.Multiply: instruction = new Multiply(); break; case InstructionType.Divide: instruction = new Divide(); break; case InstructionType.Not: instruction = new Not(); break; case InstructionType.StringEquals: instruction = new StringEquals(); break; case InstructionType.Pop: instruction = new Pop(); break; case InstructionType.ToInteger: instruction = new ToInteger(); break; case InstructionType.GetVariable: instruction = new GetVariable(); break; case InstructionType.SetVariable: instruction = new SetVariable(); break; case InstructionType.StringConcat: instruction = new StringConcat(); break; case InstructionType.GetProperty: instruction = new GetProperty(); break; case InstructionType.SetProperty: instruction = new SetProperty(); break; case InstructionType.Trace: instruction = new Trace(); break; case InstructionType.Random: instruction = new RandomNumber(); break; case InstructionType.Delete: instruction = new Delete(); break; case InstructionType.Delete2: instruction = new Delete2(); break; case InstructionType.DefineLocal: instruction = new DefineLocal(); break; case InstructionType.CallFunction: instruction = new CallFunction(); break; case InstructionType.Return: instruction = new Return(); break; case InstructionType.Modulo: instruction = new Modulo(); break; case InstructionType.NewObject: instruction = new NewObject(); break; case InstructionType.InitArray: instruction = new InitArray(); break; case InstructionType.InitObject: instruction = new InitObject(); break; case InstructionType.TypeOf: instruction = new TypeOf(); break; case InstructionType.Add2: instruction = new Add2(); break; case InstructionType.LessThan2: instruction = new LessThan2(); break; case InstructionType.Equals2: instruction = new Equals2(); break; case InstructionType.ToString: instruction = new ToString(); break; case InstructionType.PushDuplicate: instruction = new PushDuplicate(); break; case InstructionType.GetMember: instruction = new GetMember(); break; case InstructionType.SetMember: instruction = new SetMember(); break; case InstructionType.Increment: instruction = new Increment(); break; case InstructionType.Decrement: instruction = new Decrement(); break; case InstructionType.CallMethod: instruction = new CallMethod(); break; case InstructionType.Enumerate2: instruction = new Enumerate2(); break; case InstructionType.EA_PushThis: instruction = new PushThis(); break; case InstructionType.EA_PushZero: instruction = new PushZero(); break; case InstructionType.EA_PushOne: instruction = new PushOne(); break; case InstructionType.EA_CallFunc: instruction = new CallFunc(); break; case InstructionType.EA_CallMethodPop: instruction = new CallMethodPop(); break; case InstructionType.BitwiseXOr: instruction = new BitwiseXOr(); break; case InstructionType.Greater: instruction = new Greater(); break; case InstructionType.EA_PushThisVar: instruction = new PushThisVar(); break; case InstructionType.EA_PushGlobalVar: instruction = new PushGlobalVar(); break; case InstructionType.EA_ZeroVar: instruction = new ZeroVar(); break; case InstructionType.EA_PushTrue: instruction = new PushTrue(); break; case InstructionType.EA_PushFalse: instruction = new PushFalse(); break; case InstructionType.EA_PushNull: instruction = new PushNull(); break; case InstructionType.EA_PushUndefined: instruction = new PushUndefined(); break; case InstructionType.GotoFrame: instruction = new GotoFrame(); parameters.Add(Value.FromInteger(reader.ReadInt32())); break; case InstructionType.GetURL: instruction = new GetUrl(); parameters.Add(Value.FromString(reader.ReadStringAtOffset())); parameters.Add(Value.FromString(reader.ReadStringAtOffset())); break; case InstructionType.SetRegister: instruction = new SetRegister(); parameters.Add(Value.FromInteger(reader.ReadInt32())); break; case InstructionType.ConstantPool: { instruction = new ConstantPool(); var count = reader.ReadUInt32(); var constants = reader.ReadFixedSizeArrayAtOffset <uint>(() => reader.ReadUInt32(), count); foreach (var constant in constants) { parameters.Add(Value.FromConstant(constant)); } } break; case InstructionType.GotoLabel: instruction = new GotoLabel(); parameters.Add(Value.FromString(reader.ReadStringAtOffset())); break; case InstructionType.DefineFunction2: { instruction = new DefineFunction2(); var name = reader.ReadStringAtOffset(); var nParams = reader.ReadUInt32(); var nRegisters = reader.ReadByte(); var flags = reader.ReadUInt24(); //list of parameter strings var paramList = reader.ReadFixedSizeListAtOffset <FunctionArgument>(() => new FunctionArgument() { Register = reader.ReadInt32(), Parameter = reader.ReadStringAtOffset(), }, nParams); parameters.Add(Value.FromString(name)); parameters.Add(Value.FromInteger((int)nParams)); parameters.Add(Value.FromInteger((int)nRegisters)); parameters.Add(Value.FromInteger((int)flags)); foreach (var param in paramList) { parameters.Add(Value.FromInteger(param.Register)); parameters.Add(Value.FromString(param.Parameter)); } //body size of the function parameters.Add(Value.FromInteger(reader.ReadInt32())); //skip 8 bytes reader.ReadUInt64(); } break; case InstructionType.PushData: { instruction = new PushData(); var count = reader.ReadUInt32(); var constants = reader.ReadFixedSizeArrayAtOffset <uint>(() => reader.ReadUInt32(), count); foreach (var constant in constants) { parameters.Add(Value.FromConstant(constant)); } } break; case InstructionType.BranchAlways: { instruction = new BranchAlways(); var offset = reader.ReadInt32(); parameters.Add(Value.FromInteger(offset)); helper.ReportBranchOffset(offset); } break; case InstructionType.GetURL2: instruction = new GetUrl2(); break; case InstructionType.DefineFunction: { instruction = new DefineFunction(); var name = reader.ReadStringAtOffset(); //list of parameter strings var paramList = reader.ReadListAtOffset <string>(() => reader.ReadStringAtOffset()); parameters.Add(Value.FromString(name)); parameters.Add(Value.FromInteger(paramList.Count)); foreach (var param in paramList) { parameters.Add(Value.FromString(param)); } //body size of the function parameters.Add(Value.FromInteger(reader.ReadInt32())); //skip 8 bytes reader.ReadUInt64(); } break; case InstructionType.BranchIfTrue: { instruction = new BranchIfTrue(); var offset = reader.ReadInt32(); parameters.Add(Value.FromInteger(offset)); helper.ReportBranchOffset(offset); } break; case InstructionType.GotoFrame2: instruction = new GotoFrame2(); parameters.Add(Value.FromInteger(reader.ReadInt32())); break; case InstructionType.EA_PushString: instruction = new PushString(); //the constant id that should be pushed parameters.Add(Value.FromString(reader.ReadStringAtOffset())); break; case InstructionType.EA_PushConstantByte: instruction = new PushConstantByte(); //the constant id that should be pushed parameters.Add(Value.FromConstant(reader.ReadByte())); break; case InstructionType.EA_GetStringVar: instruction = new GetStringVar(); parameters.Add(Value.FromString(reader.ReadStringAtOffset())); break; case InstructionType.EA_SetStringVar: instruction = new SetStringVar(); parameters.Add(Value.FromString(reader.ReadStringAtOffset())); break; case InstructionType.EA_GetStringMember: instruction = new GetStringMember(); parameters.Add(Value.FromString(reader.ReadStringAtOffset())); break; case InstructionType.EA_SetStringMember: instruction = new SetStringMember(); parameters.Add(Value.FromString(reader.ReadStringAtOffset())); break; case InstructionType.EA_PushValueOfVar: instruction = new PushValueOfVar(); //the constant id that should be pushed parameters.Add(Value.FromConstant(reader.ReadByte())); break; case InstructionType.EA_GetNamedMember: instruction = new GetNamedMember(); parameters.Add(Value.FromConstant(reader.ReadByte())); break; case InstructionType.EA_CallNamedFuncPop: instruction = new CallNamedFuncPop(); parameters.Add(Value.FromConstant(reader.ReadByte())); break; case InstructionType.EA_CallNamedFunc: instruction = new CallNamedFunc(); parameters.Add(Value.FromConstant(reader.ReadByte())); break; case InstructionType.EA_CallNamedMethodPop: instruction = new CallNamedMethodPop(); parameters.Add(Value.FromConstant(reader.ReadByte())); break; case InstructionType.EA_PushFloat: instruction = new PushFloat(); parameters.Add(Value.FromFloat(reader.ReadSingle())); break; case InstructionType.EA_PushByte: instruction = new PushByte(); parameters.Add(Value.FromInteger(reader.ReadByte())); break; case InstructionType.EA_PushShort: instruction = new PushShort(); parameters.Add(Value.FromInteger(reader.ReadUInt16())); break; case InstructionType.End: instruction = new End(); break; case InstructionType.EA_CallNamedMethod: instruction = new CallNamedMethod(); parameters.Add(Value.FromConstant(reader.ReadByte())); break; case InstructionType.Var: instruction = new Var(); break; case InstructionType.EA_PushRegister: instruction = new PushRegister(); parameters.Add(Value.FromInteger(reader.ReadByte())); break; case InstructionType.EA_PushConstantWord: instruction = new PushConstantWord(); parameters.Add(Value.FromConstant(reader.ReadUInt16())); break; case InstructionType.EA_CallFuncPop: instruction = new CallFunctionPop(); break; case InstructionType.StrictEqual: instruction = new StrictEquals(); break; default: throw new InvalidDataException("Unimplemented bytecode instruction:" + type.ToString()); } if (instruction != null) { instruction.Parameters = parameters; instructions.Add(instructionPosition, instruction); } } } return(new InstructionCollection(instructions)); }
public void Parse() { var current = _reader.BaseStream.Position; _reader.BaseStream.Seek(_offset, SeekOrigin.Begin); bool parsing = true; bool branched = false; int branchBytes = 0; while (parsing) { //now reader the instructions var type = _reader.ReadByteAsEnum <InstructionType>(); var aligned = InstructionAlignment.IsAligned(type); if (aligned) { var padding = _reader.Align(4); if (padding > 0) { Items.Add(new Padding(padding)); if (branched) { branchBytes -= (int)padding; if (branchBytes <= 0) { branched = false; branchBytes = 0; } } } } InstructionBase instruction = null; List <Value> parameters = new List <Value>(); switch (type) { case InstructionType.ToNumber: instruction = new ToNumber(); break; case InstructionType.NextFrame: instruction = new NextFrame(); break; case InstructionType.Play: instruction = new Play(); break; case InstructionType.Stop: instruction = new Stop(); break; case InstructionType.Add: instruction = new Add(); break; case InstructionType.Subtract: instruction = new Subtract(); break; case InstructionType.Multiply: instruction = new Multiply(); break; case InstructionType.Divide: instruction = new Divide(); break; case InstructionType.Not: instruction = new Not(); break; case InstructionType.StringEquals: instruction = new StringEquals(); break; case InstructionType.Pop: instruction = new Pop(); break; case InstructionType.ToInteger: instruction = new ToInteger(); break; case InstructionType.GetVariable: instruction = new GetVariable(); break; case InstructionType.SetVariable: instruction = new SetVariable(); break; case InstructionType.StringConcat: instruction = new StringConcat(); break; case InstructionType.GetProperty: instruction = new GetProperty(); break; case InstructionType.SetProperty: instruction = new SetProperty(); break; case InstructionType.Trace: instruction = new Trace(); break; case InstructionType.Delete: instruction = new Delete(); break; case InstructionType.Delete2: instruction = new Delete2(); break; case InstructionType.DefineLocal: instruction = new DefineLocal(); break; case InstructionType.CallFunction: instruction = new CallFunction(); break; case InstructionType.Return: instruction = new Return(); break; case InstructionType.NewObject: instruction = new NewObject(); break; case InstructionType.InitArray: instruction = new InitArray(); break; case InstructionType.InitObject: instruction = new InitObject(); break; case InstructionType.TypeOf: instruction = new InitObject(); break; case InstructionType.Add2: instruction = new Add2(); break; case InstructionType.LessThan2: instruction = new LessThan2(); break; case InstructionType.Equals2: instruction = new Equals2(); break; case InstructionType.ToString: instruction = new ToString(); break; case InstructionType.PushDuplicate: instruction = new PushDuplicate(); break; case InstructionType.GetMember: instruction = new GetMember(); break; case InstructionType.SetMember: instruction = new SetMember(); break; case InstructionType.Increment: instruction = new Increment(); break; case InstructionType.Decrement: instruction = new Decrement(); break; case InstructionType.CallMethod: instruction = new CallMethod(); break; case InstructionType.Enumerate2: instruction = new Enumerate2(); break; case InstructionType.EA_PushThis: instruction = new PushThis(); break; case InstructionType.EA_PushZero: instruction = new PushZero(); break; case InstructionType.EA_PushOne: instruction = new PushOne(); break; case InstructionType.EA_CallFunc: instruction = new CallFunc(); break; case InstructionType.EA_CallMethodPop: instruction = new CallMethodPop(); break; case InstructionType.BitwiseXOr: instruction = new BitwiseXOr(); break; case InstructionType.Greater: instruction = new Greater(); break; case InstructionType.EA_PushThisVar: instruction = new PushThisVar(); break; case InstructionType.EA_PushGlobalVar: instruction = new PushGlobalVar(); break; case InstructionType.EA_ZeroVar: instruction = new ZeroVar(); break; case InstructionType.EA_PushTrue: instruction = new PushTrue(); break; case InstructionType.EA_PushFalse: instruction = new PushFalse(); break; case InstructionType.EA_PushNull: instruction = new PushNull(); break; case InstructionType.EA_PushUndefined: instruction = new PushUndefined(); break; case InstructionType.GotoFrame: instruction = new GotoFrame(); parameters.Add(Value.FromInteger(_reader.ReadInt32())); break; case InstructionType.GetURL: instruction = new GetUrl(); parameters.Add(Value.FromString(_reader.ReadStringAtOffset())); parameters.Add(Value.FromString(_reader.ReadStringAtOffset())); break; case InstructionType.SetRegister: instruction = new SetRegister(); parameters.Add(Value.FromInteger(_reader.ReadInt32())); break; case InstructionType.ConstantPool: { instruction = new ConstantPool(); var count = _reader.ReadUInt32(); var constants = _reader.ReadFixedSizeArrayAtOffset <uint>(() => _reader.ReadUInt32(), count); foreach (var constant in constants) { parameters.Add(Value.FromConstant(constant)); } } break; case InstructionType.GotoLabel: instruction = new GotoLabel(); parameters.Add(Value.FromString(_reader.ReadStringAtOffset())); break; case InstructionType.DefineFunction2: { instruction = new DefineFunction2(); var name = _reader.ReadStringAtOffset(); var nParams = _reader.ReadUInt32(); var nRegisters = _reader.ReadByte(); var flags = _reader.ReadUInt24(); //list of parameter strings var paramList = _reader.ReadFixedSizeListAtOffset <FunctionArgument>(() => new FunctionArgument() { Register = _reader.ReadInt32(), Parameter = _reader.ReadStringAtOffset(), }, nParams); parameters.Add(Value.FromString(name)); parameters.Add(Value.FromInteger((int)nParams)); parameters.Add(Value.FromInteger((int)nRegisters)); parameters.Add(Value.FromInteger((int)flags)); foreach (var param in paramList) { parameters.Add(Value.FromInteger(param.Register)); parameters.Add(Value.FromString(param.Parameter)); } //body size of the function parameters.Add(Value.FromInteger(_reader.ReadInt32())); //skip 8 bytes _reader.ReadUInt64(); } break; case InstructionType.PushData: { instruction = new PushData(); var count = _reader.ReadUInt32(); var constants = _reader.ReadFixedSizeArrayAtOffset <uint>(() => _reader.ReadUInt32(), count); foreach (var constant in constants) { parameters.Add(Value.FromConstant(constant)); } } break; case InstructionType.BranchAlways: instruction = new BranchAlways(); if (!branched) { branchBytes = _reader.ReadInt32(); parameters.Add(Value.FromInteger(branchBytes)); if (branchBytes > 0) { branchBytes += (int)instruction.Size + 1; branched = true; } } else { parameters.Add(Value.FromInteger(_reader.ReadInt32())); } break; case InstructionType.GetURL2: instruction = new GetUrl2(); break; case InstructionType.DefineFunction: { instruction = new DefineFunction(); var name = _reader.ReadStringAtOffset(); //list of parameter strings var paramList = _reader.ReadListAtOffset <string>(() => _reader.ReadStringAtOffset()); parameters.Add(Value.FromString(name)); parameters.Add(Value.FromInteger(paramList.Count)); foreach (var param in paramList) { parameters.Add(Value.FromString(param)); } //body size of the function parameters.Add(Value.FromInteger(_reader.ReadInt32())); //skip 8 bytes _reader.ReadUInt64(); } break; case InstructionType.BranchIfTrue: instruction = new BranchIfTrue(); if (!branched) { branchBytes = _reader.ReadInt32(); parameters.Add(Value.FromInteger(branchBytes)); if (branchBytes > 0) { branchBytes += (int)instruction.Size + 1; branched = true; } } else { parameters.Add(Value.FromInteger(_reader.ReadInt32())); } break; case InstructionType.GotoFrame2: instruction = new GotoFrame2(); parameters.Add(Value.FromInteger(_reader.ReadByte())); break; case InstructionType.EA_PushString: instruction = new PushString(); //the constant id that should be pushed parameters.Add(Value.FromString(_reader.ReadStringAtOffset())); break; case InstructionType.EA_PushConstantByte: instruction = new PushConstantByte(); //the constant id that should be pushed parameters.Add(Value.FromConstant(_reader.ReadByte())); break; case InstructionType.EA_GetStringVar: instruction = new GetStringVar(); parameters.Add(Value.FromString(_reader.ReadStringAtOffset())); break; case InstructionType.EA_SetStringVar: instruction = new SetStringMember(); parameters.Add(Value.FromString(_reader.ReadStringAtOffset())); break; case InstructionType.EA_GetStringMember: instruction = new GetStringMember(); parameters.Add(Value.FromString(_reader.ReadStringAtOffset())); break; case InstructionType.EA_SetStringMember: instruction = new SetStringMember(); parameters.Add(Value.FromString(_reader.ReadStringAtOffset())); break; case InstructionType.EA_PushValueOfVar: instruction = new PushValueOfVar(); //the constant id that should be pushed parameters.Add(Value.FromConstant(_reader.ReadByte())); break; case InstructionType.EA_GetNamedMember: instruction = new GetNamedMember(); parameters.Add(Value.FromConstant(_reader.ReadByte())); break; case InstructionType.EA_CallNamedFuncPop: instruction = new CallNamedFuncPop(); parameters.Add(Value.FromConstant(_reader.ReadByte())); break; case InstructionType.EA_CallNamedFunc: instruction = new CallNamedFunc(); parameters.Add(Value.FromConstant(_reader.ReadByte())); break; case InstructionType.EA_CallNamedMethodPop: instruction = new CallNamedMethodPop(); parameters.Add(Value.FromConstant(_reader.ReadByte())); break; case InstructionType.EA_PushFloat: instruction = new PushFloat(); parameters.Add(Value.FromFloat(_reader.ReadSingle())); break; case InstructionType.EA_PushByte: instruction = new PushByte(); parameters.Add(Value.FromInteger(_reader.ReadByte())); break; case InstructionType.EA_PushShort: instruction = new PushShort(); parameters.Add(Value.FromInteger(_reader.ReadUInt16())); break; case InstructionType.End: instruction = new End(); if (!branched) { parsing = false; } break; case InstructionType.EA_CallNamedMethod: instruction = new CallNamedMethod(); parameters.Add(Value.FromConstant(_reader.ReadByte())); break; case InstructionType.Var: instruction = new Var(); break; default: throw new InvalidDataException("Unimplemented bytecode instruction:" + type.ToString()); } if (instruction != null) { instruction.Parameters = parameters; Items.Add(instruction); } if (branched) { branchBytes -= (int)instruction.Size + 1; if (branchBytes <= 0) { branched = false; } } } _reader.BaseStream.Seek(current, SeekOrigin.Begin); }
public virtual void defineFunction2(DefineFunction action) { }
/// <summary> Walk the actions filling in the names of functions as we go. /// This is done by looking for DefineFunction's actions and then /// examining the content of the stack for a name. /// /// </summary> /// <param name="c">list of actions to be traversed /// </param> /// <param name="swfVersion">version of swf file that housed the ActionList (just use 7 if you don't know) /// </param> /// <param name="pool">optional; constant pool for the list of actions /// </param> /// <param name="className">optional; used to locate a constructor function (i.e if funcName == className) /// </param> /// <param name="profileOffsets">optional; is filled with offsets if a call to a /// function named 'profile' is encountered. Can be null if caller is not /// interested in obtaining this information. /// </param> public static void walkActions(ActionList c, int swfVersion, String[] pool, String className, System.Collections.IList profileOffsets) { // assumption: ActionContext c is always not null! try-catch-finally may be busted. if (c == null) { return; } System.Collections.Stack evalStack = new System.Collections.Stack(); System.Collections.Hashtable variables = new System.Collections.Hashtable(); // loop again, this time, we register all the actions... int offset; Action a; for (int i = 0; i < c.size(); i++) { offset = c.getOffset(i); a = c.getAction(i); switch (a.code) { // Flash 1 and 2 actions case ActionConstants.sactionHasLength: case ActionConstants.sactionNone: case ActionConstants.sactionGotoFrame: case ActionConstants.sactionGetURL: case ActionConstants.sactionNextFrame: case ActionConstants.sactionPrevFrame: case ActionConstants.sactionPlay: case ActionConstants.sactionStop: case ActionConstants.sactionToggleQuality: case ActionConstants.sactionStopSounds: case ActionConstants.sactionWaitForFrame: // Flash 3 Actions case ActionConstants.sactionSetTarget: case ActionConstants.sactionGotoLabel: // no action break; // Flash 4 Actions case ActionConstants.sactionAdd: case ActionConstants.sactionSubtract: case ActionConstants.sactionMultiply: case ActionConstants.sactionDivide: case ActionConstants.sactionEquals: case ActionConstants.sactionLess: case ActionConstants.sactionAnd: case ActionConstants.sactionOr: case ActionConstants.sactionStringEquals: case ActionConstants.sactionStringAdd: case ActionConstants.sactionStringLess: case ActionConstants.sactionMBStringLength: case ActionConstants.sactionGetProperty: // pop, pop, push pop(evalStack); break; case ActionConstants.sactionNot: case ActionConstants.sactionStringLength: case ActionConstants.sactionToInteger: case ActionConstants.sactionCharToAscii: case ActionConstants.sactionAsciiToChar: case ActionConstants.sactionMBCharToAscii: case ActionConstants.sactionMBAsciiToChar: case ActionConstants.sactionRandomNumber: // pop, push break; case ActionConstants.sactionGetVariable: Object key = pop(evalStack); if (variables[key] == null) { evalStack.Push(key); } else { evalStack.Push(variables[key]); } break; case ActionConstants.sactionStringExtract: case ActionConstants.sactionMBStringExtract: // pop, pop, pop, push pop(evalStack); pop(evalStack); break; case ActionConstants.sactionPush: Push p = (Push)a; System.Object o = p.value; int type = Push.getTypeCode(o); switch (type) { case ActionConstants.kPushStringType: evalStack.Push(o); break; case ActionConstants.kPushNullType: evalStack.Push("null"); break; case ActionConstants.kPushUndefinedType: evalStack.Push("undefined"); break; case ActionConstants.kPushRegisterType: evalStack.Push(registers[(int)((SByte)o) & 0xFF]); break; case ActionConstants.kPushConstant8Type: case ActionConstants.kPushConstant16Type: evalStack.Push(pool[Convert.ToInt32(((ValueType)o)) & 0xFFFF]); break; case ActionConstants.kPushFloatType: evalStack.Push(o + "F"); break; case ActionConstants.kPushBooleanType: case ActionConstants.kPushDoubleType: case ActionConstants.kPushIntegerType: evalStack.Push(o); break; default: evalStack.Push("type" + type); break; } break; case ActionConstants.sactionIf: pop(evalStack); break; case ActionConstants.sactionPop: case ActionConstants.sactionCall: case ActionConstants.sactionGotoFrame2: case ActionConstants.sactionSetTarget2: case ActionConstants.sactionRemoveSprite: case ActionConstants.sactionWaitForFrame2: case ActionConstants.sactionTrace: // pop pop(evalStack); break; case ActionConstants.sactionJump: case ActionConstants.sactionEndDrag: // no action break; case ActionConstants.sactionSetVariable: key = pop(evalStack); Object val = pop(evalStack); variables[key] = val; break; case ActionConstants.sactionGetURL2: // pop, pop pop(evalStack); pop(evalStack); break; case ActionConstants.sactionSetProperty: case ActionConstants.sactionCloneSprite: // pop, pop, pop pop(evalStack); pop(evalStack); pop(evalStack); break; case ActionConstants.sactionStartDrag: // pop, pop, pop, if the 3rd pop is non-zero, pop, pop, pop, pop pop(evalStack); pop(evalStack); Object obj = pop(evalStack); if (Int32.Parse(obj.ToString()) != 0) { pop(evalStack); pop(evalStack); pop(evalStack); pop(evalStack); } break; case ActionConstants.sactionGetTime: // push evalStack.Push(dummy); break; // Flash 5 actions case ActionConstants.sactionDelete: pop(evalStack); break; case ActionConstants.sactionDefineLocal: // pop, pop val = pop(evalStack); key = pop(evalStack); variables[key] = val; break; case ActionConstants.sactionDefineFunction: case ActionConstants.sactionDefineFunction2: DefineFunction f = (DefineFunction)a; if (swfVersion > 6 && className != null) { if (f.name == null || f.name.Length == 0) { int depth = evalStack.Count; if (depth != 0) { o = evalStack.Peek(); if (o == dummy) { f.name = ""; } else if (o != null) { f.name = o.ToString(); } } evalStack.Push(dummy); } if (f.name == "null") { f.name = ""; } if (f.name == null || f.name.Length == 0) { // do nothing... it's an anonymous function! } else if (!className.EndsWith(f.name)) { f.name = className + "." + f.name; } else { f.name = className + ".[constructor]"; } } else { if (f.name == null || f.name.Length == 0) { System.Text.StringBuilder buffer = new System.Text.StringBuilder(); Boolean bFirst = true; foreach (Object ob in evalStack) { if (ob == dummy) { break; } else if (bFirst) { buffer.Append(ob); bFirst = false; } else { buffer.Insert(0, '.'); buffer.Insert(0, ob); } } f.name = buffer.ToString(); if (f.name != null && f.name.IndexOf(".prototype.") == -1) { f.name = ""; } evalStack.Push(dummy); } } // evalActions(f.actions); break; case ActionConstants.sactionCallFunction: Object function = pop(evalStack); if (profileOffsets != null && "profile".Equals(function)) { profileOffsets.Add((Int32)(offset - 13)); // Push 1 profileOffsets.Add((Int32)(offset - 5)); // Push 'profile' profileOffsets.Add((Int32)offset); // CallFunction profileOffsets.Add((Int32)(offset + 1)); // Pop } int n = Convert.ToInt32(((System.ValueType)pop(evalStack))); for (int k = 0; k < n; k++) { pop(evalStack); } evalStack.Push(dummy); break; case ActionConstants.sactionReturn: // return function() { ... } doesn't push... pop(evalStack); break; case ActionConstants.sactionModulo: // pop, push break; case ActionConstants.sactionNewObject: pop(evalStack); int num = Convert.ToInt32(((ValueType)pop(evalStack))); for (int k = 0; k < num; k++) { pop(evalStack); } evalStack.Push(dummy); break; case ActionConstants.sactionDefineLocal2: case ActionConstants.sactionDelete2: case ActionConstants.sactionAdd2: case ActionConstants.sactionLess2: // pop pop(evalStack); break; case ActionConstants.sactionInitArray: // pop, if the first pop is non-zero, keep popping num = Convert.ToInt32(((ValueType)pop(evalStack))); for (int k = 0; k < num; k++) { pop(evalStack); } evalStack.Push(dummy); break; case ActionConstants.sactionInitObject: num = Convert.ToInt32(((ValueType)pop(evalStack))) * 2; for (int k = 0; k < num; k++) { pop(evalStack); } evalStack.Push(dummy); break; case ActionConstants.sactionTargetPath: case ActionConstants.sactionEnumerate: case ActionConstants.sactionToNumber: case ActionConstants.sactionToString: case ActionConstants.sactionTypeOf: // no action break; case ActionConstants.sactionStoreRegister: StoreRegister r = (StoreRegister)a; registers[r.register] = evalStack.Peek(); break; case ActionConstants.sactionEquals2: // pop, pop, push // if (evalStack.size() >= 2) { pop(evalStack); } break; case ActionConstants.sactionPushDuplicate: evalStack.Push(dummy); break; case ActionConstants.sactionStackSwap: // pop, pop, push, push break; case ActionConstants.sactionGetMember: // pop, pop, concat, push Object o1 = pop(evalStack); Object o2 = pop(evalStack); if (pool != null) { try { evalStack.Push(pool[Int32.Parse(o2.ToString())] + "." + pool[Int32.Parse(o1.ToString())]); } catch (Exception) { if (o1 == dummy || o2 == dummy) { evalStack.Push(dummy); } else { evalStack.Push(o2 + "." + o1); } } } else { evalStack.Push(o2 + "." + o1); } break; case ActionConstants.sactionSetMember: // pop, pop, pop pop(evalStack); pop(evalStack); pop(evalStack); break; case ActionConstants.sactionIncrement: case ActionConstants.sactionDecrement: break; case ActionConstants.sactionCallMethod: pop(evalStack); pop(evalStack); Object obj2 = pop(evalStack); if (obj2 is String) { try { n = Int32.Parse((String)obj2); } catch (FormatException) { n = 1; } } else { n = Convert.ToInt32(((ValueType)obj2)); } for (int k = 0; k < n; k++) { pop(evalStack); } evalStack.Push(dummy); break; case ActionConstants.sactionNewMethod: /*Object meth =*/ pop(evalStack); /*Object cls =*/ pop(evalStack); num = Convert.ToInt32(((ValueType)pop(evalStack))); for (int k = 0; k < num; k++) { pop(evalStack); } evalStack.Push(dummy); break; case ActionConstants.sactionWith: // pop pop(evalStack); break; case ActionConstants.sactionConstantPool: pool = ((ConstantPool)a).pool; // no action break; case ActionConstants.sactionStrictMode: break; case ActionConstants.sactionBitAnd: case ActionConstants.sactionBitOr: case ActionConstants.sactionBitLShift: // pop, push break; case ActionConstants.sactionBitXor: case ActionConstants.sactionBitRShift: case ActionConstants.sactionBitURShift: pop(evalStack); break; // Flash 6 actions case ActionConstants.sactionInstanceOf: pop(evalStack); break; case ActionConstants.sactionEnumerate2: // pop, push, more pushes? break; case ActionConstants.sactionStrictEquals: case ActionConstants.sactionGreater: case ActionConstants.sactionStringGreater: pop(evalStack); break; // FEATURE_EXCEPTIONS case ActionConstants.sactionTry: // do nothing break; case ActionConstants.sactionThrow: pop(evalStack); break; // FEATURE_AS2_INTERFACES case ActionConstants.sactionCastOp: break; case ActionConstants.sactionImplementsOp: break; // Reserved for Quicktime case ActionConstants.sactionQuickTime: break; default: break; } } }
private void collectActions(ActionList c) { // assumption: ActionContext c is always not null! try-catch-finally may be busted. if (c == null) { return; } // interprets the actions. try to assign names to anonymous functions... evalActions(c); DebugModule d = findDebugModule(c); String emptyMethodName = null; // loop again, this time, we register all the actions... for (int i = 0; i < c.size(); i++) { int ioffset = c.getOffset(i); Action a = c.getAction(i); if (emptyMethodName != null && emptyMethodName.Length != 0) { functionNames.put(ioffset, emptyMethodName); emptyMethodName = null; } if (a.code == ActionList.sactionLineRecord) { LineRecord line = (LineRecord)a; if (line.module != null) { d = line.module; if (d.name.EndsWith(".mxml")) { mxml[d.name] = d; } } continue; } if (a.code >= 256) { // something synthetic we don't care about continue; } actions.put(ioffset, (Object)codes[a.code]); modules.put(ioffset, d); switch (a.code) { case ActionConstants.sactionDefineFunction: case ActionConstants.sactionDefineFunction2: DefineFunction f = (DefineFunction)a; Int32 size = (Int32)f.codeSize; if (f.actionList.size() == 0) { emptyMethodName = f.name; } else { Int32 lineno = -1; // map all the offsets in this function to the function name for (int j = 0; j < f.actionList.size(); j++) { int o = f.actionList.getOffset(j); Action child = f.actionList.getAction(j); if (child.code == ActionList.sactionLineRecord) { if (lineno == -1) { lineno = (Int32)((LineRecord)child).lineno; } preciseLines.put(o, (Object)((LineRecord)child).lineno); } functionNames.put(o, f.name); functionSizes.put(o, (Object)size); } // map all the offsets in this function to the first line number of this function. for (int j = 0; j < f.actionList.size(); j++) { int o = f.actionList.getOffset(j); functionLines.put(o, (Object)lineno); } } collectActions(f.actionList); break; } } }