public unsafe void GetString_Empty()
        {
            var blobHeapData = new byte[]
            {
                0,          // 0

                1,          // 1: blob size
                (byte)'a',  // 2

                6,          // 3: blob size
                0,          // 4: separator
                0,          // 5: part #1
                0,          // 6: part #2
                0,          // 7: part #3
                0,          // 8: part #4
                0,          // 9: part #5
            };

            fixed(byte *ptr = blobHeapData)
            {
                var blobHeap = new BlobHeap(new MemoryBlock(ptr, blobHeapData.Length), MetadataKind.Ecma335);

                var handle = DocumentNameBlobHandle.FromOffset(3);

                var name = blobHeap.GetDocumentName(handle);

                Assert.Equal(@"", name);

                Assert.True(blobHeap.DocumentNameEquals(handle, @"", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, @"a", ignoreCase: false));
            }
        }
        public unsafe void GetString_Errors()
        {
            var blobHeapData = new byte[]
            {
                0,          // 0

                2,          // 1: blob size
                0x80,       // 2: separator
                0,          // 3: part #1
            };

            fixed(byte *ptr = blobHeapData)
            {
                var blobHeap = new BlobHeap(new MemoryBlock(ptr, blobHeapData.Length), MetadataKind.Ecma335);

                var handle = DocumentNameBlobHandle.FromOffset(1);

                Assert.Throws <BadImageFormatException>(() => blobHeap.GetDocumentName(handle));
                Assert.False(blobHeap.DocumentNameEquals(handle, "", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, "a", ignoreCase: false));

                Assert.Throws <BadImageFormatException>(() => blobHeap.GetDocumentName(default(DocumentNameBlobHandle)));
                Assert.Throws <BadImageFormatException>(() => blobHeap.GetDocumentName(DocumentNameBlobHandle.FromOffset(8)));
            }
        }
Exemple #3
0
 public MetadataHeaps()
 {
     Guids       = new GuidHeap();
     Blobs       = new BlobHeap();
     Strings     = new StringHeap();
     UserStrings = new UserStringHeap();
     Tables      = new TableHeap(this);
 }
        void WriteBlobToken(int col, MetadataTable tbl, MetadataWriter wtr, uint[] lens, object val)
        {
            BlobHeap bh = wtr.BaseStream.Root[MetadataStreamType.Blob].Heap as BlobHeap;

            if (bh.Stream.Length > ushort.MaxValue)
            {
                wtr.Write((uint)(val as BlobToken).Token.Value);
            }
            else
            {
                wtr.Write((ushort)(val as BlobToken).Token.Value);
            }
        }
Exemple #5
0
        TokenTypes IMetadataProvider.Read(TokenTypes token, out byte[] result)
        {
            if (TokenTypes.Blob == (TokenTypes.TableMask & token))
            {
                BlobHeap bheap = (BlobHeap)_streams[(int)HeapType.Blob];
                result = bheap.ReadBlob(ref token);
            }
            else
            {
                throw new ArgumentException(@"Invalid token for a blob.", @"token");
            }

            return(token);
        }
Exemple #6
0
        public uint CreateAssemblyRef(IAssembly assembly)
        {
            var rid = TablesHeap.AssemblyRefTable.Create();
            var row = new RawAssemblyRefRow((ushort)assembly.Version.Major, (ushort)assembly.Version.Minor,
                                            (ushort)assembly.Version.Build, (ushort)assembly.Version.Revision,
                                            (uint)assembly.Attributes,
                                            BlobHeap.Create(GetPublicKeyOrTokenBytes(assembly.PublicKeyOrToken)),
                                            StringsHeap.Create(assembly.Name),
                                            StringsHeap.Create(assembly.Culture),
                                            BlobHeap.Create((assembly as AssemblyRef)?.Hash));

            TablesHeap.AssemblyRefTable.Set(rid, ref row);
            return(rid);
        }
Exemple #7
0
        public uint CreateAssemblyRef(IAssembly assembly)
        {
            var rid = TablesHeap.AssemblyRefTable.Create();
            var row = TablesHeap.AssemblyRefTable.Get(rid);

            row.MajorVersion     = (ushort)assembly.Version.Major;
            row.MinorVersion     = (ushort)assembly.Version.Minor;
            row.BuildNumber      = (ushort)assembly.Version.Build;
            row.RevisionNumber   = (ushort)assembly.Version.Revision;
            row.Flags            = (uint)assembly.Attributes;
            row.PublicKeyOrToken = BlobHeap.Create(GetPublicKeyOrTokenBytes(assembly.PublicKeyOrToken));
            row.Name             = StringsHeap.Create(assembly.Name);
            row.Locale           = StringsHeap.Create(assembly.Culture);
            row.HashValue        = BlobHeap.Create((assembly as AssemblyRef)?.Hash);
            return(rid);
        }
        public unsafe void GetString1()
        {
            var blobHeapData = new byte[]
            {
                0,          // 0

                2,          // 1: blob size
                (byte)'a',  // 2
                (byte)'b',  // 3

                3,          // 4: blob size
                (byte)'x',  // 5
                (byte)'y',  // 6
                (byte)'z',  // 7

                3,          // 8: blob size
                (byte)'\\', // 9: separator
                1,          // 10: part #1
                4,          // 11: part #2
            };

            fixed(byte *ptr = blobHeapData)
            {
                var blobHeap = new BlobHeap(new MemoryBlock(ptr, blobHeapData.Length), MetadataKind.Ecma335);

                var handle = DocumentNameBlobHandle.FromOffset(8);

                var name = blobHeap.GetDocumentName(handle);

                Assert.Equal(@"ab\xyz", name);

                Assert.True(blobHeap.DocumentNameEquals(handle, @"ab\xyz", ignoreCase: false));
                Assert.True(blobHeap.DocumentNameEquals(handle, @"Ab\xYz", ignoreCase: true));

                Assert.False(blobHeap.DocumentNameEquals(handle, @"", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, @"a", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, @"ab", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, @"ab\", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, @"ab\x", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, @"ab\xy", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, @"abc\xyz", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, @"Ab\xYzz", ignoreCase: true));
                Assert.False(blobHeap.DocumentNameEquals(handle, @"Ab\xYz\", ignoreCase: true));
            }
        }
        static object ReadBlobToken(int col, MetadataTable tbl, MetadataReader rdr, uint[] lens)
        {
            if (rdr.BaseStream.Root[MetadataStreamType.Blob] == null)
            {
                rdr.ReadUInt16();
                return(BlobToken.Null);
            }
            BlobHeap bh = rdr.BaseStream.Root[MetadataStreamType.Blob].Heap as BlobHeap;
            uint     tkn;

            if (bh.Stream.Length > ushort.MaxValue)
            {
                tkn = rdr.ReadUInt32();
            }
            else
            {
                tkn = rdr.ReadUInt16();
            }
            return(bh.Resolve(new MetadataToken(tkn)));
        }
        public unsafe void GetString_NonAscii()
        {
            var blobHeapData = new byte[]
            {
                0,          // 0

                3,          // 1: blob size
                0xe1,       // 2: U+1234 in UTF8
                0x88,       // 3
                0xb4,       // 4

                1,          // 5: blob size
                (byte)'b',  // 6

                4,          // 7: blob size
                (byte)'a',  // 8: separator
                5,          // 9: part #1
                1,          // 10: part #2
                5,          // 11: part #3
            };

            fixed(byte *ptr = blobHeapData)
            {
                var blobHeap = new BlobHeap(new MemoryBlock(ptr, blobHeapData.Length), MetadataKind.Ecma335);

                var handle = DocumentNameBlobHandle.FromOffset(7);

                var name = blobHeap.GetDocumentName(handle);

                Assert.Equal("ba\u1234ab", name);

                Assert.True(blobHeap.DocumentNameEquals(handle, "ba\u1234ab", ignoreCase: false));
                Assert.True(blobHeap.DocumentNameEquals(handle, "BA\u1234AB", ignoreCase: true));

                Assert.False(blobHeap.DocumentNameEquals(handle, "b\u1234ab", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, "a\u1234ab", ignoreCase: false));
                Assert.False(blobHeap.DocumentNameEquals(handle, "ba\u1234abb", ignoreCase: false));
            }
        }
        /// <summary>
        /// We want to know if a given method implements a redirected interface.
        /// For example, if we are given the method RemoveAt on a class "A"
        /// which implements the IVector interface (which is redirected
        /// to IList in .NET) then this method would return true. The most
        /// likely reason why we would want to know this is that we wish to hide
        /// (mark private) all methods which implement methods on a redirected
        /// interface.
        /// </summary>
        /// <param name="memberRef">The declaration token for the method</param>
        /// <param name="isIDisposable">
        /// Returns true if the redirected interface is <see cref="IDisposable"/>.
        /// </param>
        /// <returns>True if the method implements a method on a redirected interface.
        /// False otherwise.</returns>
        private bool ImplementsRedirectedInterface(MemberReferenceHandle memberRef, out bool isIDisposable)
        {
            isIDisposable = false;

            EntityHandle parent = MemberRefTable.GetClass(memberRef);

            TypeReferenceHandle typeRef;

            if (parent.Kind == HandleKind.TypeReference)
            {
                typeRef = (TypeReferenceHandle)parent;
            }
            else if (parent.Kind == HandleKind.TypeSpecification)
            {
                BlobHandle blob = TypeSpecTable.GetSignature((TypeSpecificationHandle)parent);
                BlobReader sig  = new BlobReader(BlobHeap.GetMemoryBlock(blob));

                if (sig.Length < 2 ||
                    sig.ReadByte() != (byte)CorElementType.ELEMENT_TYPE_GENERICINST ||
                    sig.ReadByte() != (byte)CorElementType.ELEMENT_TYPE_CLASS)
                {
                    return(false);
                }

                EntityHandle token = sig.ReadTypeHandle();
                if (token.Kind != HandleKind.TypeReference)
                {
                    return(false);
                }

                typeRef = (TypeReferenceHandle)token;
            }
            else
            {
                return(false);
            }

            return(GetProjectionIndexForTypeReference(typeRef, out isIDisposable) >= 0);
        }
        public unsafe void GetString_IgnoreSeparatorCase()
        {
            var blobHeapData = new byte[]
            {
                0,          // 0

                1,          // 1: blob size
                (byte)'b',  // 2

                3,          // 3: blob size
                (byte)'a',  // 4: separator
                1,          // 5: part #1
                1,          // 6: part #2
            };

            fixed(byte *ptr = blobHeapData)
            {
                var blobHeap = new BlobHeap(new MemoryBlock(ptr, blobHeapData.Length), MetadataKind.Ecma335);

                var handle = DocumentNameBlobHandle.FromOffset(3);

                var name = blobHeap.GetDocumentName(handle);

                Assert.Equal("bab", name);

                Assert.True(blobHeap.DocumentNameEquals(handle, "bab", ignoreCase: false));
                Assert.True(blobHeap.DocumentNameEquals(handle, "BAB", ignoreCase: true));
                Assert.True(blobHeap.DocumentNameEquals(handle, "bAb", ignoreCase: true));
                Assert.True(blobHeap.DocumentNameEquals(handle, "BaB", ignoreCase: true));

                Assert.False(blobHeap.DocumentNameEquals(handle, "", ignoreCase: true));
                Assert.False(blobHeap.DocumentNameEquals(handle, "B", ignoreCase: true));
                Assert.False(blobHeap.DocumentNameEquals(handle, "bA", ignoreCase: true));
                Assert.False(blobHeap.DocumentNameEquals(handle, "bAbA", ignoreCase: true));
            }
        }
Exemple #13
0
        DotNetHeap[] CreateENCHeaps()
        {
            var         list        = new List <DotNetHeap>();
            StringsHeap stringsHeap = null;
            USHeap      usHeap      = null;
            BlobHeap    blobHeap    = null;
            GUIDHeap    guidHeap    = null;
            TablesHeap  tablesHeap  = null;

            foreach (var ssh in storageStreamHeaders)
            {
                var span = new HexBufferSpan(file.Buffer, ssh.DataSpan);

                switch (ssh.Name.ToUpperInvariant())
                {
                case "#STRINGS":
                    if (stringsHeap == null)
                    {
                        stringsHeap = new StringsHeapImpl(span);
                        list.Add(stringsHeap);
                        continue;
                    }
                    break;

                case "#US":
                    if (usHeap == null)
                    {
                        usHeap = new USHeapImpl(span);
                        list.Add(usHeap);
                        continue;
                    }
                    break;

                case "#BLOB":
                    if (blobHeap == null)
                    {
                        blobHeap = new BlobHeapImpl(span);
                        list.Add(blobHeap);
                        continue;
                    }
                    break;

                case "#GUID":
                    if (guidHeap == null)
                    {
                        guidHeap = new GUIDHeapImpl(span);
                        list.Add(guidHeap);
                        continue;
                    }
                    break;

                case "#~":                      // Only if #Schema is used
                case "#-":
                    if (tablesHeap == null && span.Length >= TablesHeapImpl.MinimumSize)
                    {
                        tablesHeap = new TablesHeapImpl(span, TablesHeapType.ENC);
                        list.Add(tablesHeap);
                        continue;
                    }
                    break;
                }
                list.Add(new UnknownHeapImpl(span));
            }
            return(list.ToArray());
        }
    internal MetaDataRoot m_mdr;                                // MetaData Root table

    /*********************************************************************************************************************
    *	1) Parse the MetaData Root table.
    *
    *	2) Initialize the various heaps.
    *
    *	3) Initialize "m_oldNameHash", "m_classTree", and "m_freeSpaceList".
    *
    *	4) Initialize the various BitArrays.
    *
    *	5) Set the total numbers of the elements (types, methods, fields, properties, events, and parameters).
    *********************************************************************************************************************/
    internal MetaData(ref byte[] buf)
    {
        int       i, ptHeapIndex = -1;
        Exception toBeThrown;

        m_buffer = buf;

        // Ok.  Now we can build a reader and a writer over the memory m_buffer.
        MemoryStream memStream = new MemoryStream(m_buffer);
        BinaryReader reader    = new BinaryReader(memStream);
        BinaryWriter writer    = new BinaryWriter(memStream);

        AllHeaders all = new AllHeaders(ref reader);
        NTHeader   nth = all.m_ntHeader;

        SectionHeader[] sh = all.m_sectionHeaders;

                #if DEBUG0
        Console.WriteLine("Runtime Header Data Directory");
        Console.WriteLine("rva: " + nth.m_DataDirectory[14].RVA + "; size: " + nth.m_DataDirectory[14].Size + Environment.NewLine);
        Console.WriteLine("offset to MetaData section: " + (long)(nth.m_DataDirectory[14].RVA + 8));
                #endif

        // Read the RVA of the physical MetaData section from the Runtime Header Data Directory.
        reader.BaseStream.Seek((long)(nth.m_DataDirectory[14].RVA + 8), SeekOrigin.Begin);
        m_startPos = reader.ReadUInt64();

        // Theoretically, startPos can be 64 bit long, but in practice, 32 bits are enough.
        // TODO : Check the docs.  The following assertion will fail.
        // Debug.Assert((startPos >> 32) == 0);
        m_startPos = m_startPos & 0xffffffff;                                                   // use the least significant 4 bytes as the offset

        m_mdr = new MetaDataRoot(ref reader, ref m_buffer, m_startPos);

        // We need to initialize the #Strings heap and the #Blob heap before dealing with the #~ heap.
        for (i = 0; i < m_mdr.m_numStreams; i++)
        {
            if (m_mdr.m_streamHeaders[i].name.Equals("#Strings\0"))
            {
                m_strHeap = new StringHeap(ref m_buffer, m_startPos + m_mdr.m_streamHeaders[i].offset, m_mdr.m_streamHeaders[i].size);
            }

            else if (m_mdr.m_streamHeaders[i].name.Equals("#Blob\0"))
            {
                m_blobHeap = new BlobHeap(ref m_buffer, m_startPos + m_mdr.m_streamHeaders[i].offset, m_mdr.m_streamHeaders[i].size);
            }

            else if (m_mdr.m_streamHeaders[i].name.Equals("#~\0") || m_mdr.m_streamHeaders[i].name.Equals("#-\0"))
            {
                ptHeapIndex = i;
            }
        }

        if (ptHeapIndex != -1)
        {
            m_heap = new PTHeap(ref reader, ref writer, ref m_strHeap, m_startPos + m_mdr.m_streamHeaders[ptHeapIndex].offset);
        }
        else
        {
            toBeThrown = new InvalidFileFormat("Invalid CIL binary file format.");
            throw toBeThrown;
        }
    }
Exemple #15
0
 public override void VisitBlobHeap(BlobHeap heap)
 {
     this.asm.StaticArray(moduleName + " BlobHeap", heap.Data);
 }
Exemple #16
0
        public static void Write(IWriterError helper, Metadata systemMetadata, DataWriter writer, BlobHeap blobHeap, IList <PdbImport> imports)
        {
            var blobWriter = new ImportScopeBlobWriter(helper, systemMetadata, blobHeap);

            blobWriter.Write(writer, imports);
        }
Exemple #17
0
 ImportScopeBlobWriter(IWriterError helper, Metadata systemMetadata, BlobHeap blobHeap)
 {
     this.helper         = helper;
     this.systemMetadata = systemMetadata;
     this.blobHeap       = blobHeap;
 }
 public virtual void VisitBlobHeap(BlobHeap heap)
 {
 }
Exemple #19
0
 internal BlobToken(BlobHeap h) : base(h)
 {
 }
Exemple #20
0
        DotNetHeap[] CreateCompressedHeaps()
        {
            var         list        = new List <DotNetHeap>();
            StringsHeap stringsHeap = null;
            USHeap      usHeap      = null;
            BlobHeap    blobHeap    = null;
            GUIDHeap    guidHeap    = null;
            TablesHeap  tablesHeap  = null;
            PdbHeap     pdbHeap     = null;

            for (int i = storageStreamHeaders.Length - 1; i >= 0; i--)
            {
                var ssh  = storageStreamHeaders[i];
                var span = new HexBufferSpan(file.Buffer, ssh.DataSpan);

                switch (ssh.Name)
                {
                case "#Strings":
                    if (stringsHeap == null)
                    {
                        stringsHeap = new StringsHeapImpl(span);
                        list.Add(stringsHeap);
                        continue;
                    }
                    break;

                case "#US":
                    if (usHeap == null)
                    {
                        usHeap = new USHeapImpl(span);
                        list.Add(usHeap);
                        continue;
                    }
                    break;

                case "#Blob":
                    if (blobHeap == null)
                    {
                        blobHeap = new BlobHeapImpl(span);
                        list.Add(blobHeap);
                        continue;
                    }
                    break;

                case "#GUID":
                    if (guidHeap == null)
                    {
                        guidHeap = new GUIDHeapImpl(span);
                        list.Add(guidHeap);
                        continue;
                    }
                    break;

                case "#~":
                    if (tablesHeap == null && span.Length >= TablesHeapImpl.MinimumSize)
                    {
                        tablesHeap = new TablesHeapImpl(span, TablesHeapType.Compressed);
                        list.Add(tablesHeap);
                        continue;
                    }
                    break;

                case "#!":
                    list.Add(new HotHeapImpl(span));
                    continue;

                case "#Pdb":
                    if (pdbHeap == null && span.Length >= PdbHeapImpl.MinimumSize)
                    {
                        pdbHeap = new PdbHeapImpl(span);
                        list.Add(pdbHeap);
                        continue;
                    }
                    break;
                }
                list.Add(new UnknownHeapImpl(span));
            }

            list.Reverse();
            return(list.ToArray());
        }
 private void CacheBlobs(BlobHeap blobHeap)
 {
     Constructor.Log("Caching .NET blob signatures.");
     blobHeap.ReadAllBlobs();
 }
        /// <summary>
        /// Reads a blob heap entry.
        /// </summary>
        /// <param name="token">The token of the blob heap entry to read.</param>
        /// <returns></returns>
        byte[] IMetadataProvider.ReadBlob(HeapIndexToken token)
        {
            BlobHeap bheap = (BlobHeap)_streams[(int)HeapType.Blob];

            return(bheap.ReadBlob(token));
        }
Exemple #23
0
        internal MetadataRow(MetadataTable tbl, bool needInit)
            : base(tbl)
        {
            vals = new object[tbl.TableDef.Columns.Length];
            par  = tbl;
            if (!needInit)
            {
                return;
            }

            BlobHeap    bh = tbl.Heap.Stream.Root[MetadataStreamType.Blob].Heap as BlobHeap;
            StringsHeap sh = tbl.Heap.Stream.Root[MetadataStreamType.Strings].Heap as StringsHeap;
            GUIDHeap    gh = tbl.Heap.Stream.Root[MetadataStreamType.GUID].Heap as GUIDHeap;

            foreach (MetadataColumn col in tbl.Columns)
            {
                if (col.Type is Type)
                {
                    if ((col.Type as Type).IsEnum)
                    {
                        this[col.Index] = Enum.ToObject(col.Type as Type, 0);
                    }
                    else
                    {
                        switch ((col.Type as Type).FullName)
                        {
                        case "System.Byte":
                            this[col.Index] = (byte)0;
                            break;

                        case "System.UInt16":
                            this[col.Index] = (ushort)0;
                            break;

                        case "System.UInt32":
                            this[col.Index] = (uint)0;
                            break;

                        case "NetPE.Core.Rva":
                            this[col.Index] = (Rva)0;
                            break;

                        case "NetPE.Core.Metadata.BlobToken":
                            this[col.Index] = bh.Resolve(new MetadataToken(MetadataTokenType.Unknown, 0));
                            break;

                        case "NetPE.Core.Metadata.GUIDToken":
                            this[col.Index] = gh.Resolve(new MetadataToken(MetadataTokenType.Unknown, 0));
                            break;

                        case "NetPE.Core.Metadata.StringToken":
                            this[col.Index] = sh.Resolve(new MetadataToken(MetadataTokenType.Unknown, 0));
                            break;
                        }
                    }
                }
                else if (col.Type is TableType)
                {
                    this[col.Index] = new TableToken(tbl.Heap, new MetadataToken((MetadataTokenType)(TableType)col.Type, 0));
                }
                else if (col.Type is CodedIndex)
                {
                    this[col.Index] = new TableToken(tbl.Heap, new MetadataToken((MetadataTokenType)CodedIndexDefs.MdCodedIndexDefs[(CodedIndex)col.Type].TableTypes[0].Key, 0));
                }
            }
        }
 public virtual void VisitBlobHeap(BlobHeap heap)
 {
 }
Exemple #25
0
        private void InitializeStreamReaders(
            ref MemoryBlock metadataRoot,
            StreamHeader[] streamHeaders,
            out MetadataStreamKind metadataStreamKind,
            out MemoryBlock metadataTableStream,
            out MemoryBlock standalonePdbStream)
        {
            metadataTableStream = default(MemoryBlock);
            standalonePdbStream = default(MemoryBlock);
            metadataStreamKind  = MetadataStreamKind.Illegal;

            foreach (StreamHeader streamHeader in streamHeaders)
            {
                switch (streamHeader.Name)
                {
                case COR20Constants.StringStreamName:
                    if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size)
                    {
                        throw new BadImageFormatException("NotEnoughSpaceForStringStream");
                    }

                    break;

                case COR20Constants.BlobStreamName:
                    if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size)
                    {
                        throw new BadImageFormatException("NotEnoughSpaceForBlobStream");
                    }

                    this.BlobHeap = new BlobHeap(metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size), _metadataKind);
                    break;

                case COR20Constants.GUIDStreamName:
                    if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size)
                    {
                        throw new BadImageFormatException("NotEnoughSpaceForGUIDStream");
                    }

                    break;

                case COR20Constants.UserStringStreamName:
                    if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size)
                    {
                        throw new BadImageFormatException("NotEnoughSpaceForBlobStream");
                    }

                    break;

                case COR20Constants.CompressedMetadataTableStreamName:
                    if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size)
                    {
                        throw new BadImageFormatException("NotEnoughSpaceForMetadataStream");
                    }

                    metadataStreamKind  = MetadataStreamKind.Compressed;
                    metadataTableStream = metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size);
                    break;

                case COR20Constants.UncompressedMetadataTableStreamName:
                    if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size)
                    {
                        throw new BadImageFormatException("NotEnoughSpaceForMetadataStream");
                    }

                    metadataStreamKind  = MetadataStreamKind.Uncompressed;
                    metadataTableStream = metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size);
                    break;

                case COR20Constants.MinimalDeltaMetadataTableStreamName:
                    if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size)
                    {
                        throw new BadImageFormatException("NotEnoughSpaceForMetadataStream");
                    }

                    // the content of the stream is ignored
                    this.IsMinimalDelta = true;
                    break;

                case COR20Constants.StandalonePdbStreamName:
                    if (metadataRoot.Length < streamHeader.Offset + streamHeader.Size)
                    {
                        throw new BadImageFormatException("NotEnoughSpaceForMetadataStream");
                    }

                    standalonePdbStream = metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size);
                    break;

                default:
                    // Skip unknown streams. Some obfuscators insert invalid streams.
                    continue;
                }
            }

            if (IsMinimalDelta && metadataStreamKind != MetadataStreamKind.Uncompressed)
            {
                throw new BadImageFormatException("InvalidMetadataStreamFormat");
            }
        }