/// <summary> /// /// </summary> /// <param name="sourceStream"></param> protected override void Parse(BinaryReader sourceStream) { _DebugType = AVM2.Static.VariableLengthInteger.ReadU8(sourceStream); _Index = AVM2.Static.VariableLengthInteger.ReadU30(sourceStream); _Reg = AVM2.Static.VariableLengthInteger.ReadU8(sourceStream); _Extra = AVM2.Static.VariableLengthInteger.ReadU30(sourceStream); if (0 != _Extra) { // Of course, Adobe Flash CS4 makes use of this field AbcFormatException abcfe = new AbcFormatException("Extra (reserved) field in Debug instruction used: 0x" + _Extra.ToString("X")); Log.Warn(this, abcfe); //throw abcfe; //Log.Warn(this, "Extra (reserved) field in Debug instruction used: 0x" + _Extra.ToString("X")); } }
/// <summary> /// /// </summary> /// <param name="source"></param> public void Parse( Stream source ) { _Ns = new List<uint>(); UInt32 setMemberCount = VariableLengthInteger.ReadU30( source ); for ( uint i = 0; i < setMemberCount; i++ ) { UInt32 entry = VariableLengthInteger.ReadU30( source ); if ( 0 == entry ) { AbcFormatException fe = new AbcFormatException( "Namespace set entry is 0" ); Log.Error(this, fe ); throw fe; } _Ns.Add( entry ); } }
/// <summary> /// /// </summary> /// <param name="source"></param> public void Parse(Stream source) { // UNTESTED _Name = VariableLengthInteger.ReadU30(source); if (0 == _Name) { AbcFormatException fe = new AbcFormatException("Metadata_info with Name == 0"); Log.Error(this, fe); throw fe; } UInt32 itemCount = VariableLengthInteger.ReadU30(source); _ItemInfo = new List<Metadata_item_info>(); for (uint i = 0; i < itemCount; i++) { Metadata_item_info mdii = new Metadata_item_info(); mdii.Parse(source); _ItemInfo.Add(mdii); } }
/// <summary> /// /// </summary> /// <param name="source"></param> public void Parse( Stream source ) { //Log.Debug(this, "Offset : " + source.Position); _Name = VariableLengthInteger.ReadU30( source ); _Supername = VariableLengthInteger.ReadU30( source ); byte flags = VariableLengthInteger.ReadU8( source ); _FlagClassSealed = ( ( flags & 0x01 ) != 0 ); _FlagClassFinal = ( ( flags & 0x02 ) != 0 ); _FlagClassInterface = ( ( flags & 0x04 ) != 0 ); _FlagClassProtectedNs = ( ( flags & 0x08 ) != 0 ); if ( ( flags & 0xF0 ) != 0 ) { AbcFormatException fe = new AbcFormatException( "Reserved flags used in Instance_Info" ); Log.Error(this, fe ); throw fe; } if ( _FlagClassProtectedNs ) { _ProtectedNs = VariableLengthInteger.ReadU30( source ); } UInt32 interfaceCount = VariableLengthInteger.ReadU30( source ); _Interface = new List<UInt32>( (int)interfaceCount ); for ( uint i = 0; i < interfaceCount; i++ ) { UInt32 interf = VariableLengthInteger.ReadU30( source ); if ( 0 == interf ) { AbcFormatException fe = new AbcFormatException( "Instance_info interface index is 0" ); Log.Error(this, fe ); throw fe; } _Interface.Add( interf ); } _Iinit = VariableLengthInteger.ReadU30( source ); UInt32 traitCount = VariableLengthInteger.ReadU30( source ); _Trait = new List<Traits_info>( ( int )traitCount ); for ( uint i = 0; i < traitCount; i++ ) { Traits_info ti = new Traits_info(); ti.Parse( source ); _Trait.Add( ti ); } }
/// <summary> /// Parses this object out of a stream /// </summary> /// <param name="source">The source stream.</param> public void Parse(Stream source) { long startPos = source.Position; _MinorVersion = VariableLengthInteger.ReadU16(source); _MajorVersion = VariableLengthInteger.ReadU16(source); String s1 = String.Format("ABC Version {0:d}.{1:d}", _MajorVersion, _MinorVersion); Log.Debug(this, s1); if (_MajorVersion != 46) { AbcFormatException fe = new AbcFormatException("ABC major version mismatch: " + _MajorVersion.ToString("d") + " (expected: 46)"); Log.Error(this, fe); throw fe; } if (_MinorVersion != 16) { String s2 = String.Format("ABC minor version {d:0} is not equal to expected version 16", _MinorVersion); Log.Warn(this, s2); } // (1) ConstantPool String s3 = String.Format("0x{0:X08}: ConstantPool", source.Position - startPos); Log.Debug(this, s3); _ConstantPool = new Cpool_info(); _ConstantPool.Parse(source); Log.Debug(this, _ConstantPool.ToString(this)); // (2) Method_Info String s4 = String.Format("0x{0:X08}: Method_info", source.Position - startPos); Log.Debug(this, s4); UInt32 methodCount = VariableLengthInteger.ReadU30(source); _Method = new List<Method_info>(); for (uint i = 0; i < methodCount; i++) { Method_info mi = new Method_info(); mi.Parse(source); _Method.Add(mi); } String s5 = String.Format("{0:d} Methods", _Method.Count); Log.Debug(this, s5); // (3) Metadata String s6 = String.Format("0x{0:X08}: Metadata", source.Position - startPos); // //Log.Debug(this, s6); UInt32 metadataInfoCount = VariableLengthInteger.ReadU30(source); _Metadata = new List<Metadata_info>(); for (uint i = 0; i < metadataInfoCount; i++) { Metadata_info mdi = new Metadata_info(); mdi.Parse(source); _Metadata.Add(mdi); } String s7 = String.Format("{0:d} Metadata entries", _Metadata.Count); Log.Debug(this, s7); // (4) Instance_info String s8 = String.Format("0x{0:X08}: Instance_info", source.Position - startPos); Log.Debug(this, s8); UInt32 classCount = VariableLengthInteger.ReadU30(source); _Instance = new List<Instance_info>((int)classCount); for (uint i = 0; i < classCount; i++) { Instance_info ii = new Instance_info(); ii.Parse(source); _Instance.Add(ii); } String s9 = String.Format("{0:d} Instances", _Instance.Count); Log.Debug(this, s9); // (5) Class_info String s10 = String.Format("0x{0:X08}: Class_info", source.Position - startPos); Log.Debug(this, s10); _Class = new List<Class_info>((int)classCount); for (uint i = 0; i < classCount; i++) { Class_info ci = new Class_info(); ci.Parse(source); _Class.Add(ci); } String s11 = String.Format("{0:d} Classes", _Class.Count); Log.Debug(this, s11); // (6) Script_info String s12 = String.Format("0x{0:X08}: Script_info", source.Position - startPos); Log.Debug(this, s12); UInt32 scriptCount = VariableLengthInteger.ReadU30(source); _Script = new List<Script_info>((int)scriptCount); for (uint i = 0; i < scriptCount; i++) { Script_info si = new Script_info(); si.Parse(source); _Script.Add(si); } String s13 = String.Format("{0:d} Scripts", _Script.Count); Log.Debug(this, s13); // (7) Method_body_info String s14 = String.Format("0x{0:X08}: MethodBody_info", source.Position - startPos); Log.Debug(this, s14); UInt32 methodBodyCount = VariableLengthInteger.ReadU30(source); if (methodBodyCount > methodCount) { String s15 = String.Format("More method bodies ({0:d}) than methods ({1:d})!", methodBodyCount, methodCount); Log.Warn(this, s15); } _MethodBody = new Dictionary<UInt32, Method_body_info>((int)methodBodyCount); for (uint i = 0; i < methodBodyCount; i++) { Method_body_info mbi = new Method_body_info(); mbi.Parse(source); _MethodBody.Add(mbi.Method, mbi); } String s16 = String.Format("{0:d} Method bodies", _MethodBody.Count); Log.Debug(this, s16); if (source.Position != source.Length) { AbcFormatException fe = new AbcFormatException( "Trailing garbage after reading ABC file: at offset 0x" + source.Position.ToString("X08") + " of 0x" + source.Length.ToString("X08")); Log.Error(this, fe); throw fe; } String s17 = String.Format("0x{0:X08}: End", source.Position - startPos); Log.Debug(this, s17); Log.Debug(this, "Done reading ABC"); }
/// <summary> /// /// </summary> /// <param name="kindId"></param> public AbstractMultinameEntry( byte kindId ) { if ( !Enum.IsDefined( typeof( MultinameType ), kindId ) ) { AbcFormatException fe = new AbcFormatException( "Invalid Multiname entry kind " + kindId.ToString( "X2" ) ); Log.Error(this, fe ); throw ( fe ); } _Type = ( MultinameType )kindId; }
/// <summary> /// /// </summary> /// <param name="source"></param> /// <returns></returns> private AbstractMultinameEntry MultinameEntryFactory(Stream source) { BinaryReader br = new BinaryReader(source); byte kind = br.ReadByte(); if (!Enum.IsDefined(typeof(MultinameType), kind)) { AbcFormatException fe = new AbcFormatException("Invalid multiname type 0x" + kind.ToString("X2")); Log.Error(this, fe); throw fe; } AbstractMultinameEntry product = null; switch ((MultinameType)kind) { case MultinameType.QName: case MultinameType.QNameA: product = new MultinameQname(kind); product.Namespace = VariableLengthInteger.ReadU30(source); product.NameIndex = VariableLengthInteger.ReadU30(source); break; case MultinameType.RTQName: case MultinameType.RTQNameA: product = new MultinameRTQname(kind); product.NameIndex = VariableLengthInteger.ReadU30(source); break; case MultinameType.RTQNameL: case MultinameType.RTQNameLA: product = new MultinameRTQnameL(kind); break; case MultinameType.Multiname: case MultinameType.MultinameA: product = new MultinameMultiname(kind); product.NameIndex = VariableLengthInteger.ReadU30(source); product.NsSet = VariableLengthInteger.ReadU30(source); break; case MultinameType.MultinameL: case MultinameType.MultinameLA: product = new MultinameMultinameL(kind); product.NsSet = VariableLengthInteger.ReadU30(source); break; case MultinameType.Multiname0x1D: product = new Multiname0x1D(kind); ((Multiname0x1D)product).Parse(source); break; default: Exception e = new Exception("Internal error, Multiname type " + kind.ToString("X2") + " reached end of factory!!"); Log.Error(this, e); throw e; } return product; }
/// <summary> /// Parses this object out of a stream /// </summary> /// <param name="source">The input stream</param> public void Parse(Stream source) { // "The “0” entry of the integer array is not present in the abcFile; it // represents the zero value for the purposes of providing values for optional // parameters and field initialization." // UInt32 integerCount = VariableLengthInteger.ReadU30(source); // Note: integerCount == 0 seems to be valid Integers = new List<Int32>((int)integerCount); Integers.Add((int)0); for (uint i = 1; i < integerCount; i++) { Integers.Add(VariableLengthInteger.ReadS32(source)); } // // "The “0” entry of the uinteger array is not present in the abcFile; it // represents the zero value for the purposes of providing values for optional // parameters and field initialization." // UInt32 uIntegerCount = VariableLengthInteger.ReadU30(source); // Note: uIntegerCount == 0 seems to be valid UIntegers = new List<UInt32>((int)uIntegerCount); UIntegers.Add((UInt32)0); for (uint i = 1; i < uIntegerCount; i++) { UIntegers.Add(VariableLengthInteger.ReadU32(source)); } // // Double // UInt32 doubleCount = VariableLengthInteger.ReadU30(source); //Note: doubleCount == 0 seems to be valid too Doubles = new List<double>(); Doubles.Add(Double.NaN); BinaryReader br = new BinaryReader(source); for (uint i = 1; i < doubleCount; i++) { Doubles.Add(br.ReadDouble()); } // // String pool // UInt32 stringCount = VariableLengthInteger.ReadU30(source); // // "The value of string_count is the number of entries in the string array, plus one." // if (1 > stringCount) { AbcFormatException fe = new AbcFormatException("Constant pool string count < 1"); Log.Error(this, fe); throw fe; } stringCount--; Strings = new List<string>(); // Money quote: "Entry “0” of the string array is not present in the abcFile; it // represents the empty string in most contexts but is also used to represent the // “any” name in others (known as “*” in ActionScript)." Strings.Add(""); // WARNING: Adobe Flash CS4 often includes an empty string at _String[1] (the first // actually present in the file), _despite_ the fact that _String[0] is // defined to be there for that purpose. for (uint i = 0; i < stringCount; i++) { Strings.Add(StringInfo.Read(source)); } // // Namespaces // UInt32 namespaceCount = VariableLengthInteger.ReadU30(source); // // "The value of namespace_count is the number of entries in // the namespace array, plus one." // if (1 > namespaceCount) { /* AbcFormatException fe = new AbcFormatException( "Name space count < 1" ); Log.Error(this, fe ); throw fe; */ Log.Warn(this, "Namespace count < 1"); namespaceCount = 1; } namespaceCount--; Namespaces = new List<Namespace_info>(); Namespaces.Add(new Namespace_info()); for (uint i = 0; i < namespaceCount; i++) { Namespace_info nsi = new Namespace_info(); nsi.Parse(source); Namespaces.Add(nsi); } // // NS Set // UInt32 nsSetCount = VariableLengthInteger.ReadU30(source); // another "plus one" case if (1 > nsSetCount) { /* AbcFormatException fe = new AbcFormatException( "Namespace set count < 1" ); Log.Error(this, fe ); throw fe; */ Log.Warn(this, "NsSetCount < 1"); nsSetCount = 1; } nsSetCount--; NsSets = new List<Ns_set_info>(); NsSets.Add(new Ns_set_info()); // dummy entry for array[0] not in file for (uint i = 0; i < nsSetCount; i++) { Ns_set_info nssi = new Ns_set_info(); nssi.Parse(source); NsSets.Add(nssi); } // // Multinames // UInt32 multinameCount = VariableLengthInteger.ReadU30(source); // another "plus one" case, doh! if (1 > multinameCount) { /* AbcFormatException fe = new AbcFormatException( "Multiname count < 1" ); Log.Error(this, fe ); throw fe; */ Log.Warn(this, "Multiname count < 1"); multinameCount = 1; } multinameCount--; Multinames = new List<AbstractMultinameEntry>(); Multinames.Add(new MultinameRTQnameL((byte)MultinameType.RTQNameL)); // dummy entry for array[0] not in file for (uint i = 0; i < multinameCount; i++) { AbstractMultinameEntry entry = MultinameEntryFactory(source); Multinames.Add(entry); } }
/// <summary> /// /// </summary> /// <param name="source"></param> public void Parse(Stream source) { Log.Debug(this, "Offset : " + source.Position); _Value = VariableLengthInteger.ReadU30(source); byte type = VariableLengthInteger.ReadU8(source); if (!Enum.IsDefined(typeof(OptionType), type)) { AbcFormatException fe = new AbcFormatException("Option_detail entry type 0x" + type.ToString("X02") + " is invalid"); Log.Error(this, fe); throw fe; } _Type = (OptionType)type; }
/// <summary> /// /// </summary> /// <param name="source"></param> /// <returns></returns> private TraitsData_Slot ParseSlot(Stream source) { TraitsData_Slot s = new TraitsData_Slot(); s.SlotID = VariableLengthInteger.ReadU30(source); s.TypeName = VariableLengthInteger.ReadU30(source); s.Vindex = VariableLengthInteger.ReadU30(source); if (0 != s.Vindex) { byte kind = VariableLengthInteger.ReadU8(source); if (!Enum.IsDefined(typeof(OptionType), kind)) { AbcFormatException fe = new AbcFormatException("TraitsData Slot invalid constant type 0x" + kind.ToString("X02")); Log.Error(this, fe); throw fe; } s.Vkind = (OptionType)kind; } else { s.Vkind = OptionType.TotallyInvalid; } return s; }
/// <summary> /// /// </summary> /// <param name="source"></param> public void Parse(Stream source) { // UNTESTED Name = VariableLengthInteger.ReadU30(source); byte kind = VariableLengthInteger.ReadU8(source); byte kindType = (byte)(kind & 0x0F); byte kindAttr = (byte)((kind & 0xF0) >> 4); if (!Enum.IsDefined(typeof(TraitType), kindType)) { AbcFormatException fe = new AbcFormatException("Invalid Traits_info kind " + kindType.ToString("d")); Log.Error(this, fe); throw fe; } Type = (TraitType)kindType; // // "Any other combination of attribute with kind is ignored." // - so we test for it. // AttribFinal = (kindAttr & 0x01) != 0 ? true : false; AttribOverride = (kindAttr & 0x02) != 0 ? true : false; AttribMetadata = (kindAttr & 0x04) != 0 ? true : false; if (AttribFinal && (!((Type == TraitType.Trait_Getter) || (Type == TraitType.Trait_Setter) || (Type == TraitType.Trait_Method)))) { AbcFormatException fe = new AbcFormatException("ATTR_Final with trait type " + Enum.GetName(typeof(TraitType), Type)); Log.Error(this, fe); throw fe; } if (AttribOverride && (!((Type == TraitType.Trait_Getter) || (Type == TraitType.Trait_Setter) || (Type == TraitType.Trait_Method)))) { AbcFormatException fe = new AbcFormatException("ATTR_Override with trait type " + Enum.GetName(typeof(TraitType), Type)); Log.Error(this, fe); throw fe; } // // Just to point out how this works: only one of them // is going to be valid // switch (Type) { case TraitType.Trait_Const: case TraitType.Trait_Slot: _Data_Slot = ParseSlot(source); break; case TraitType.Trait_Class: _Data_Class = ParseClass(source); break; case TraitType.Trait_Function: _Data_Function = ParseFunction(source); break; case TraitType.Trait_Method: case TraitType.Trait_Getter: case TraitType.Trait_Setter: _Data_Method = ParseMethod(source); break; default: Exception e = new Exception("Internal error: invalid _Type 0x" + Type.ToString("X02") + " reached end of switch"); Log.Error(this, e); throw e; } if (AttribMetadata) { UInt32 metadataCount = VariableLengthInteger.ReadU30(source); _Metadata = new List<UInt32>((int)metadataCount); for (uint i = 0; i < metadataCount; i++) { UInt32 metav = VariableLengthInteger.ReadU30(source); _Metadata.Add(metav); } } }
/// <summary> /// /// </summary> /// <param name="source"></param> public void Parse(Stream source) { BinaryReader br = new BinaryReader(source); byte kindId = br.ReadByte(); if (!Enum.IsDefined(typeof(NamespaceKind), kindId)) { AbcFormatException fe = new AbcFormatException("Namespace kind 0x" + kindId.ToString("X2") + " is undefined"); Log.Error(this, fe); throw fe; } _Kind = (NamespaceKind)kindId; _Name = VariableLengthInteger.ReadU30(source); }
/// <summary> /// /// </summary> /// <param name="source"></param> /// <returns></returns> private static UInt32 Read32( Stream source ) { UInt32 value = 0; bool moreToFollow = false; int shift = 0; long pos = source.Position; UInt32 addition = 0; byte b = 0; byte[] buf = new byte[ 2 ]; do { source.Read( buf, 0, 1 ); b = buf[ 0 ]; moreToFollow = ( 0 != ( b & 0x80 ) ); addition = unchecked( ( UInt32 )( ( b & 0x7F ) << shift ) ); value = value | addition ; shift = shift + 7; } while ( ( ( source.Position - pos ) < 5 ) && moreToFollow ); if ( moreToFollow ) { AbcFormatException fe = new AbcFormatException( "Variable length integer indicating > 5 bytes (stream pos: 0x" + pos.ToString( "X08" ) + ", value=0x" + value.ToString( "X08" ) + ", last byte=0x" + b.ToString( "X02" ) + ")" ); Log.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, fe); throw fe; } if ( ( ( source.Position - pos ) == 5 ) && ( ( b & 0xF0 ) != 0 ) ) { AbcFormatException fe = new AbcFormatException( "Overlong variable length integer detected! (stream pos: 0x" + pos.ToString( "X08" ) + ", value=0x" + value.ToString( "X08" ) + ", last byte=0x" + b.ToString( "X02" ) + ")" ); Log.Error(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType, fe); throw fe; } return value; }
/// <summary> /// /// </summary> /// <param name="source"></param> public void Parse(Stream source) { Log.Debug(this, "Offset : " + source.Position); UInt32 paramCount = VariableLengthInteger.ReadU30(source); ReturnType = VariableLengthInteger.ReadU30(source); ParamType = new List<UInt32>(); for (uint i = 0; i < paramCount; i++) { ParamType.Add(VariableLengthInteger.ReadU30(source)); } Name = VariableLengthInteger.ReadU30(source); byte flags = VariableLengthInteger.ReadU8(source); FlagNeedArguments = ((flags & 0x01) != 0); FlagActivation = ((flags & 0x02) != 0); FlagNeedRest = ((flags & 0x04) != 0); FlagHasOptional = ((flags & 0x08) != 0); FlagSetDxns = ((flags & 0x40) != 0); FlagHasParamNames = ((flags & 0x80) != 0); if ((flags & 0x30) != 0) { AbcFormatException fe = new AbcFormatException("Reserved flags used in Method_info"); Log.Error(this, fe); throw fe; } if (FlagHasOptional) { UInt32 optionCount = VariableLengthInteger.ReadU30(source); if (optionCount > paramCount) { AbcFormatException fe = new AbcFormatException("optionCount (" + optionCount.ToString("d") + ") > paramCount (" + paramCount.ToString("d") + ") in Method_info"); Log.Error(this, fe); throw fe; } Option = new List<Option_detail>(); for (uint i = 0; i < optionCount; i++) { Option_detail od = new Option_detail(); od.Parse(source); Option.Add(od); } } if (FlagHasParamNames) { ParamNames = new List<UInt32>(); for (uint i = 0; i < paramCount; i++) { ParamNames.Add(VariableLengthInteger.ReadU30(source)); } } if (FlagNeedRest && FlagNeedArguments) { AbcFormatException fe = new AbcFormatException("NeedRest and NeedArguments both set"); Log.Error(this, fe); throw fe; } }