object ReadValue(SerializationType etype, TypeSig argType, out TypeSig realArgType) { if (!recursionCounter.Increment()) { throw new CABlobParserException("Too much recursion"); } object result; switch (etype) { case SerializationType.Boolean: realArgType = module.CorLibTypes.Boolean; result = reader.ReadByte() != 0; break; case SerializationType.Char: realArgType = module.CorLibTypes.Char; result = (char)reader.ReadUInt16(); break; case SerializationType.I1: realArgType = module.CorLibTypes.SByte; result = reader.ReadSByte(); break; case SerializationType.U1: realArgType = module.CorLibTypes.Byte; result = reader.ReadByte(); break; case SerializationType.I2: realArgType = module.CorLibTypes.Int16; result = reader.ReadInt16(); break; case SerializationType.U2: realArgType = module.CorLibTypes.UInt16; result = reader.ReadUInt16(); break; case SerializationType.I4: realArgType = module.CorLibTypes.Int32; result = reader.ReadInt32(); break; case SerializationType.U4: realArgType = module.CorLibTypes.UInt32; result = reader.ReadUInt32(); break; case SerializationType.I8: realArgType = module.CorLibTypes.Int64; result = reader.ReadInt64(); break; case SerializationType.U8: realArgType = module.CorLibTypes.UInt64; result = reader.ReadUInt64(); break; case SerializationType.R4: realArgType = module.CorLibTypes.Single; result = reader.ReadSingle(); break; case SerializationType.R8: realArgType = module.CorLibTypes.Double; result = reader.ReadDouble(); break; case SerializationType.String: realArgType = module.CorLibTypes.String; result = ReadUTF8String(); break; // It's ET.ValueType if it's eg. a ctor enum arg type case (SerializationType)ElementType.ValueType: if (argType == null) { throw new CABlobParserException("Invalid element type"); } realArgType = argType; result = ReadEnumValue(GetEnumUnderlyingType(argType)); break; // It's ET.Object if it's a ctor object arg type case (SerializationType)ElementType.Object: case SerializationType.TaggedObject: realArgType = ReadFieldOrPropType(); var arraySig = realArgType as SZArraySig; if (arraySig != null) { result = ReadArrayArgument(arraySig); } else { TypeSig tmpType; result = ReadValue((SerializationType)realArgType.ElementType, realArgType, out tmpType); } break; // It's ET.Class if it's eg. a ctor System.Type arg type case (SerializationType)ElementType.Class: var tdr = argType as TypeDefOrRefSig; if (tdr != null && tdr.DefinitionAssembly.IsCorLib() && tdr.Namespace == "System") { if (tdr.TypeName == "Type") { result = ReadValue(SerializationType.Type, tdr, out realArgType); break; } if (tdr.TypeName == "String") { result = ReadValue(SerializationType.String, tdr, out realArgType); break; } if (tdr.TypeName == "Object") { result = ReadValue(SerializationType.TaggedObject, tdr, out realArgType); break; } } // Assume it's an enum that couldn't be resolved realArgType = argType; return(ReadEnumValue(null)); case SerializationType.Type: realArgType = argType; result = ReadType(); break; case SerializationType.Enum: realArgType = ReadType(); result = ReadEnumValue(GetEnumUnderlyingType(realArgType)); break; default: throw new CABlobParserException("Invalid element type"); } recursionCounter.Decrement(); return(result); }
bool ReadCore(out TypeSig type, out object value) { if (!recursionCounter.Increment()) { type = null; value = null; return(false); } bool res; ITypeDefOrRef tdr; UTF8String ns, name; var et = (ElementType)reader.ReadByte(); switch (et) { case ElementType.Boolean: type = module.CorLibTypes.Boolean; value = reader.ReadBoolean(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } res = true; break; case ElementType.Char: type = module.CorLibTypes.Char; value = (char)reader.ReadUInt16(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } res = true; break; case ElementType.I1: type = module.CorLibTypes.SByte; value = reader.ReadSByte(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } res = true; break; case ElementType.U1: type = module.CorLibTypes.Byte; value = reader.ReadByte(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } res = true; break; case ElementType.I2: type = module.CorLibTypes.Int16; value = reader.ReadInt16(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } res = true; break; case ElementType.U2: type = module.CorLibTypes.UInt16; value = reader.ReadUInt16(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } res = true; break; case ElementType.I4: type = module.CorLibTypes.Int32; value = reader.ReadInt32(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } res = true; break; case ElementType.U4: type = module.CorLibTypes.UInt32; value = reader.ReadUInt32(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } res = true; break; case ElementType.I8: type = module.CorLibTypes.Int64; value = reader.ReadInt64(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } res = true; break; case ElementType.U8: type = module.CorLibTypes.UInt64; value = reader.ReadUInt64(); if (reader.Position < reader.Length) { type = ReadTypeDefOrRefSig(); } res = true; break; case ElementType.R4: type = module.CorLibTypes.Single; value = reader.ReadSingle(); res = true; break; case ElementType.R8: type = module.CorLibTypes.Double; value = reader.ReadDouble(); res = true; break; case ElementType.String: type = module.CorLibTypes.String; value = ReadString(); res = true; break; case ElementType.Ptr: res = Read(out type, out value); if (res) { type = new PtrSig(type); } break; case ElementType.ByRef: res = Read(out type, out value); if (res) { type = new ByRefSig(type); } break; case ElementType.Object: type = module.CorLibTypes.Object; value = null; res = true; break; case ElementType.ValueType: tdr = ReadTypeDefOrRef(); type = tdr.ToTypeSig(); value = null; if (GetName(tdr, out ns, out name) && ns == stringSystem && tdr.DefinitionAssembly.IsCorLib()) { if (name == stringDecimal) { if (reader.Length - reader.Position != 13) { goto default; } try { byte b = reader.ReadByte(); value = new Decimal(reader.ReadInt32(), reader.ReadInt32(), reader.ReadInt32(), (b & 0x80) != 0, (byte)(b & 0x7F)); } catch { goto default; } } else if (name == stringDateTime) { if (reader.Length - reader.Position != 8) { goto default; } try { value = new DateTime(reader.ReadInt64()); } catch { goto default; } } } if (value == null && reader.Position != reader.Length) { value = reader.ReadRemainingBytes(); } res = true; break; case ElementType.Class: type = new ClassSig(ReadTypeDefOrRef()); value = reader.Position == reader.Length ? null : reader.ReadRemainingBytes(); res = true; break; case ElementType.CModReqd: tdr = ReadTypeDefOrRef(); res = Read(out type, out value); if (res) { type = new CModReqdSig(tdr, type); } break; case ElementType.CModOpt: tdr = ReadTypeDefOrRef(); res = Read(out type, out value); if (res) { type = new CModOptSig(tdr, type); } break; case ElementType.Var: case ElementType.Array: case ElementType.GenericInst: case ElementType.TypedByRef: case ElementType.I: case ElementType.U: case ElementType.FnPtr: case ElementType.SZArray: case ElementType.MVar: case ElementType.End: case ElementType.Void: case ElementType.ValueArray: case ElementType.R: case ElementType.Internal: case ElementType.Module: case ElementType.Sentinel: case ElementType.Pinned: default: Debug.Fail("Unsupported element type in LocalConstant sig blob: " + et.ToString()); res = false; type = null; value = null; break; } recursionCounter.Decrement(); return(res); }
public static bool TryReadNumeric(IImageStream stream, long end, out object value) { value = null; if (stream.Position + 2 > end) { return(false); } var numLeaf = (NumericLeaf)stream.ReadUInt16(); if (numLeaf < NumericLeaf.LF_NUMERIC) { value = (short)numLeaf; return(true); } switch (numLeaf) { case NumericLeaf.LF_CHAR: if (stream.Position > end) { return(false); } value = stream.ReadSByte(); return(true); case NumericLeaf.LF_SHORT: if (stream.Position + 2 > end) { return(false); } value = stream.ReadInt16(); return(true); case NumericLeaf.LF_USHORT: if (stream.Position + 2 > end) { return(false); } value = stream.ReadUInt16(); return(true); case NumericLeaf.LF_LONG: if (stream.Position + 4 > end) { return(false); } value = stream.ReadInt32(); return(true); case NumericLeaf.LF_ULONG: if (stream.Position + 4 > end) { return(false); } value = stream.ReadUInt32(); return(true); case NumericLeaf.LF_REAL32: if (stream.Position + 4 > end) { return(false); } value = stream.ReadSingle(); return(true); case NumericLeaf.LF_REAL64: if (stream.Position + 8 > end) { return(false); } value = stream.ReadDouble(); return(true); case NumericLeaf.LF_QUADWORD: if (stream.Position + 8 > end) { return(false); } value = stream.ReadInt64(); return(true); case NumericLeaf.LF_UQUADWORD: if (stream.Position + 8 > end) { return(false); } value = stream.ReadUInt64(); return(true); case NumericLeaf.LF_VARSTRING: if (stream.Position + 2 > end) { return(false); } int varStrLen = stream.ReadUInt16(); if (stream.Position + varStrLen > end) { return(false); } value = Encoding.UTF8.GetString(stream.ReadBytes(varStrLen)); return(true); case NumericLeaf.LF_VARIANT: if (stream.Position + 0x10 > end) { return(false); } int v0 = stream.ReadInt32(); int v1 = stream.ReadInt32(); int v2 = stream.ReadInt32(); int v3 = stream.ReadInt32(); byte scale = (byte)(v0 >> 16); if (scale <= 28) { value = new decimal(v2, v3, v1, v0 < 0, scale); } else { value = null; } return(true); default: return(false); } }
/// <summary> /// Reads the next type /// </summary> /// <returns>A new <see cref="TypeSig"/> instance or <c>null</c> if invalid element type</returns> TypeSig ReadType() { if (!recursionCounter.Increment()) { return(null); } uint num; TypeSig nextType, result = null; switch ((ElementType)reader.ReadByte()) { case ElementType.Void: result = corLibTypes.Void; break; case ElementType.Boolean: result = corLibTypes.Boolean; break; case ElementType.Char: result = corLibTypes.Char; break; case ElementType.I1: result = corLibTypes.SByte; break; case ElementType.U1: result = corLibTypes.Byte; break; case ElementType.I2: result = corLibTypes.Int16; break; case ElementType.U2: result = corLibTypes.UInt16; break; case ElementType.I4: result = corLibTypes.Int32; break; case ElementType.U4: result = corLibTypes.UInt32; break; case ElementType.I8: result = corLibTypes.Int64; break; case ElementType.U8: result = corLibTypes.UInt64; break; case ElementType.R4: result = corLibTypes.Single; break; case ElementType.R8: result = corLibTypes.Double; break; case ElementType.String: result = corLibTypes.String; break; case ElementType.TypedByRef: result = corLibTypes.TypedReference; break; case ElementType.I: result = corLibTypes.IntPtr; break; case ElementType.U: result = corLibTypes.UIntPtr; break; case ElementType.Object: result = corLibTypes.Object; break; case ElementType.Ptr: result = new PtrSig(ReadType()); break; case ElementType.ByRef: result = new ByRefSig(ReadType()); break; case ElementType.ValueType: result = new ValueTypeSig(ReadTypeDefOrRef()); break; case ElementType.Class: result = new ClassSig(ReadTypeDefOrRef()); break; case ElementType.FnPtr: result = new FnPtrSig(ReadSig()); break; case ElementType.SZArray: result = new SZArraySig(ReadType()); break; case ElementType.CModReqd: result = new CModReqdSig(ReadTypeDefOrRef(), ReadType()); break; case ElementType.CModOpt: result = new CModOptSig(ReadTypeDefOrRef(), ReadType()); break; case ElementType.Sentinel: result = new SentinelSig(); break; case ElementType.Pinned: result = new PinnedSig(ReadType()); break; case ElementType.Var: if (!reader.ReadCompressedUInt32(out num)) { break; } result = new GenericVar(num); break; case ElementType.MVar: if (!reader.ReadCompressedUInt32(out num)) { break; } result = new GenericMVar(num); break; case ElementType.ValueArray: nextType = ReadType(); if (!reader.ReadCompressedUInt32(out num)) { break; } result = new ValueArraySig(nextType, num); break; case ElementType.Module: if (!reader.ReadCompressedUInt32(out num)) { break; } result = new ModuleSig(num, ReadType()); break; case ElementType.GenericInst: nextType = ReadType(); if (!reader.ReadCompressedUInt32(out num)) { break; } var genericInstSig = new GenericInstSig(nextType as ClassOrValueTypeSig, num); var args = genericInstSig.GenericArguments; for (uint i = 0; i < num; i++) { args.Add(ReadType()); } result = genericInstSig; break; case ElementType.Array: nextType = ReadType(); uint rank; if (!reader.ReadCompressedUInt32(out rank)) { break; } if (rank == 0) { result = new ArraySig(nextType, rank); break; } if (!reader.ReadCompressedUInt32(out num)) { break; } var sizes = new List <uint>((int)num); for (uint i = 0; i < num; i++) { uint size; if (!reader.ReadCompressedUInt32(out size)) { goto exit; } sizes.Add(size); } if (!reader.ReadCompressedUInt32(out num)) { break; } var lowerBounds = new List <int>((int)num); for (uint i = 0; i < num; i++) { int size; if (!reader.ReadCompressedInt32(out size)) { goto exit; } lowerBounds.Add(size); } result = new ArraySig(nextType, rank, sizes, lowerBounds); break; case ElementType.Internal: IntPtr address; if (IntPtr.Size == 4) { address = new IntPtr(reader.ReadInt32()); } else { address = new IntPtr(reader.ReadInt64()); } result = helper.ConvertRTInternalAddress(address); break; case ElementType.End: case ElementType.R: default: result = null; break; } exit: recursionCounter.Decrement(); return(result); }