Пример #1
0
 internal BlobReader(MemoryBlock block)
 {
     Debug.Assert(BitConverter.IsLittleEndian && block.Length >= 0 && (block.Pointer != null || block.Length == 0));
     _block = block;
     _currentPointer = block.Pointer;
     _endPointer = block.Pointer + block.Length;
 }
Пример #2
0
        public unsafe void DefaultDecodingFallbackMatchesBcl()
        {
            byte[] buffer;
            int bytesRead;

            var decoder = MetadataStringDecoder.DefaultUTF8;

            // dangling lead byte
            fixed (byte* ptr = (buffer = new byte[] { 0xC0 }))
            {
                string s = new MemoryBlock(ptr, buffer.Length).PeekUtf8NullTerminated(0, null, decoder, out bytesRead);
                Assert.Equal("\uFFFD", new MemoryBlock(ptr, buffer.Length).PeekUtf8NullTerminated(0, null, decoder, out bytesRead));
                Assert.Equal(s, Encoding.UTF8.GetString(buffer));
                Assert.Equal(buffer.Length, bytesRead);

                s = new MemoryBlock(ptr, buffer.Length).PeekUtf8NullTerminated(0, Encoding.UTF8.GetBytes("Hello"), decoder, out bytesRead);
                Assert.Equal("Hello\uFFFD", s);
                Assert.Equal(s, "Hello" + Encoding.UTF8.GetString(buffer));
                Assert.Equal(buffer.Length, bytesRead);

                Assert.Equal("\uFFFD", new MemoryBlock(ptr, buffer.Length).PeekUtf8(0, buffer.Length));
            }

            // overlong encoding
            fixed (byte* ptr = (buffer = new byte[] { (byte)'a', 0xC0, 0xAF, (byte)'b', 0x0 }))
            {
                var block = new MemoryBlock(ptr, buffer.Length);
                Assert.Equal("a\uFFFD\uFFFDb", block.PeekUtf8NullTerminated(0, null, decoder, out bytesRead));
                Assert.Equal(buffer.Length, bytesRead);
            }
            // TODO: There are a bunch more error cases of course, but this is enough to break the old code
            // and we now just call the BCL, so from a white box perspective, we needn't get carried away.
        }
Пример #3
0
        internal MethodDebugInformationTableReader(
            int numberOfRows,
            int documentRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset)
        {
            NumberOfRows = numberOfRows;
            _isDocumentRefSmall = documentRefSize == 2;
            _isBlobHeapRefSizeSmall = blobHeapRefSize == 2;

            _sequencePointsOffset = DocumentOffset + documentRefSize;
            RowSize = _sequencePointsOffset + blobHeapRefSize;

            Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows);
        }
Пример #4
0
        private MethodBodyBlock(
            bool localVariablesInitialized,
            ushort maxStack,
            StandaloneSignatureHandle localSignatureHandle,
            MemoryBlock il,
            ImmutableArray<ExceptionRegion> exceptionRegions,
            int size)
        {
            Debug.Assert(!exceptionRegions.IsDefault);

            this.localVariablesInitialized = localVariablesInitialized;
            this.maxStack = maxStack;
            this.localSignature = localSignatureHandle;
            this.il = il;
            this.exceptionRegions = exceptionRegions;
            this.size = size;
        }
Пример #5
0
        internal DocumentTableReader(
            int numberOfRows,
            int guidHeapRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset)
        {
            NumberOfRows = numberOfRows;
            _isGuidHeapRefSizeSmall = guidHeapRefSize == 2;
            _isBlobHeapRefSizeSmall = blobHeapRefSize == 2;

            _hashAlgorithmOffset = NameOffset + blobHeapRefSize;
            _hashOffset = _hashAlgorithmOffset + guidHeapRefSize;
            _languageOffset = _hashOffset + blobHeapRefSize;
            RowSize = _languageOffset + guidHeapRefSize;

            Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows);
        }
Пример #6
0
 internal ModuleTableReader(
     int numberOfRows,
     int stringHeapRefSize,
     int guidHeapRefSize,
     MemoryBlock containingBlock,
     int containingBlockOffset
 )
 {
     this.NumberOfRows = numberOfRows;
     _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
     _IsGUIDHeapRefSizeSmall = guidHeapRefSize == 2;
     _GenerationOffset = 0;
     _NameOffset = _GenerationOffset + sizeof(UInt16);
     _MVIdOffset = _NameOffset + stringHeapRefSize;
     _EnCIdOffset = _MVIdOffset + guidHeapRefSize;
     _EnCBaseIdOffset = _EnCIdOffset + guidHeapRefSize;
     this.RowSize = _EnCBaseIdOffset + guidHeapRefSize;
     this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * (int)numberOfRows);
 }
Пример #7
0
        private void TestUtf8NullTerminatedFastCompare(
            MemoryBlock block,
            int offset,
            char terminator,
            string comparand,
            int comparandOffset,
            bool ignoreCase,
            MemoryBlock.FastComparisonResult expectedResult,
            int expectedFirstDifferenceIndex)
        {
            int actualFirstDifferenceIndex;
            var actualResult = block.Utf8NullTerminatedFastCompare(offset, comparand, comparandOffset, out actualFirstDifferenceIndex, terminator, ignoreCase);

            Assert.Equal(expectedResult, actualResult);
            Assert.Equal(expectedFirstDifferenceIndex, actualFirstDifferenceIndex);
        }
Пример #8
0
        public unsafe void Utf8NullTerminatedFastCompare()
        {
            byte[] heap;
            MetadataStringDecoder decoder = MetadataStringDecoder.DefaultUTF8;
            const bool HonorCase = false;
            const bool IgnoreCase = true;
            const char terminator_0 = '\0';
            const char terminator_F = 'F';
            const char terminator_X = 'X';
            const char terminator_x = 'x';

            fixed (byte* heapPtr = (heap = new byte[] { (byte)'F', 0, (byte)'X', (byte)'Y', /* U+12345 (\ud808\udf45) */ 0xf0, 0x92, 0x8d, 0x85 }))
            {
                var block = new MemoryBlock(heapPtr, heap.Length);

                TestUtf8NullTerminatedFastCompare(block, 0, terminator_0, "F", 0, HonorCase, MemoryBlock.FastComparisonResult.Equal, 1);
                TestUtf8NullTerminatedFastCompare(block, 0, terminator_0, "f", 0, IgnoreCase, MemoryBlock.FastComparisonResult.Equal, 1);

                TestUtf8NullTerminatedFastCompare(block, 0, terminator_F, "", 0, IgnoreCase, MemoryBlock.FastComparisonResult.Equal, 0);
                TestUtf8NullTerminatedFastCompare(block, 0, terminator_F, "*", 1, IgnoreCase, MemoryBlock.FastComparisonResult.Equal, 1);

                TestUtf8NullTerminatedFastCompare(block, 0, terminator_0, "FF", 0, HonorCase, MemoryBlock.FastComparisonResult.TextStartsWithBytes, 1);
                TestUtf8NullTerminatedFastCompare(block, 0, terminator_0, "fF", 0, IgnoreCase, MemoryBlock.FastComparisonResult.TextStartsWithBytes, 1);
                TestUtf8NullTerminatedFastCompare(block, 0, terminator_0, "F\0", 0, HonorCase, MemoryBlock.FastComparisonResult.TextStartsWithBytes, 1);
                TestUtf8NullTerminatedFastCompare(block, 0, terminator_X, "F\0", 0, HonorCase, MemoryBlock.FastComparisonResult.TextStartsWithBytes, 1);

                TestUtf8NullTerminatedFastCompare(block, 2, terminator_0, "X", 0, HonorCase, MemoryBlock.FastComparisonResult.BytesStartWithText, 1);
                TestUtf8NullTerminatedFastCompare(block, 2, terminator_0, "x", 0, IgnoreCase, MemoryBlock.FastComparisonResult.BytesStartWithText, 1);
                TestUtf8NullTerminatedFastCompare(block, 2, terminator_x, "XY", 0, IgnoreCase, MemoryBlock.FastComparisonResult.BytesStartWithText, 2);

                TestUtf8NullTerminatedFastCompare(block, 3, terminator_0, "yZ", 0, IgnoreCase, MemoryBlock.FastComparisonResult.Unequal, 1);
                TestUtf8NullTerminatedFastCompare(block, 4, terminator_0, "a", 0, HonorCase, MemoryBlock.FastComparisonResult.Unequal, 0);
                TestUtf8NullTerminatedFastCompare(block, 4, terminator_0, "\ud808", 0, HonorCase, MemoryBlock.FastComparisonResult.Inconclusive, 0);
                TestUtf8NullTerminatedFastCompare(block, 4, terminator_0, "\ud808\udf45", 0, HonorCase, MemoryBlock.FastComparisonResult.Inconclusive, 0);

            }
        }
Пример #9
0
        private static unsafe void TestComparison(MemoryBlock block, int offset, string value, string heapSubstr, MetadataStringDecoder decoder, bool ignoreCase)
        {
            // equals:
            bool actualEq = block.Utf8NullTerminatedEquals(offset, value, decoder, terminator: '\0', ignoreCase: ignoreCase);
            bool expectedEq = string.Equals(heapSubstr, value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
            Assert.Equal(expectedEq, actualEq);

            // starts with:
            bool actualSW = block.Utf8NullTerminatedStartsWith(offset, value, decoder, terminator: '\0', ignoreCase: ignoreCase);
            bool expectedSW = heapSubstr.StartsWith(value, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
            Assert.Equal(actualSW, expectedSW);
        }
Пример #10
0
        internal ConstantTableReader(
            int numberOfRows,
            bool declaredSorted,
            int hasConstantRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset
        )
        {
            this.NumberOfRows = numberOfRows;
            _IsHasConstantRefSizeSmall = hasConstantRefSize == 2;
            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
            _TypeOffset = 0;
            _ParentOffset = _TypeOffset + sizeof(Byte) + 1; // Alignment here (+1)...
            _ValueOffset = _ParentOffset + hasConstantRefSize;
            this.RowSize = _ValueOffset + blobHeapRefSize;
            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, (int)(this.RowSize * numberOfRows));

            if (!declaredSorted && !CheckSorted())
            {
                Throw.TableNotSorted(TableIndex.Constant);
            }
        }
Пример #11
0
        public unsafe void PeekReference()
        {
            var table = new byte[]
            {
                0xff, 0xff, 0xff, 0x00, // offset 0
                0xff, 0xff, 0xff, 0x01, // offset 4
                0xff, 0xff, 0xff, 0x1f, // offset 8
                0xff, 0xff, 0xff, 0x2f, // offset 12
                0xff, 0xff, 0xff, 0xff, // offset 16
            };

            fixed (byte* tablePtr = table)
            {
                var block = new MemoryBlock(tablePtr, table.Length);

                Assert.Equal(0x0000ffff, block.PeekReference(0, smallRefSize: true));
                Assert.Equal(0x0000ffff, block.PeekHeapReference(0, smallRefSize: true));
                Assert.Equal(0x0000ffffu, block.PeekReferenceUnchecked(0, smallRefSize: true));

                Assert.Equal(0x00ffffff, block.PeekReference(0, smallRefSize: false));
                Assert.Throws<BadImageFormatException>(() => block.PeekReference(4, smallRefSize: false));
                Assert.Throws<BadImageFormatException>(() => block.PeekReference(16, smallRefSize: false));

                Assert.Equal(0x1fffffff, block.PeekHeapReference(8, smallRefSize: false));
                Assert.Throws<BadImageFormatException>(() => block.PeekHeapReference(12, smallRefSize: false));
                Assert.Throws<BadImageFormatException>(() => block.PeekHeapReference(16, smallRefSize: false));

                Assert.Equal(0x01ffffffu, block.PeekReferenceUnchecked(4, smallRefSize: false));
                Assert.Equal(0x1fffffffu, block.PeekReferenceUnchecked(8, smallRefSize: false));
                Assert.Equal(0x2fffffffu, block.PeekReferenceUnchecked(12, smallRefSize: false));
                Assert.Equal(0xffffffffu, block.PeekReferenceUnchecked(16, smallRefSize: false));
            }
        }
Пример #12
0
        private unsafe void TestSearch(string heapValue, int offset, string[] values)
        {
            byte[] heap;

            fixed (byte* heapPtr = (heap = Encoding.UTF8.GetBytes(heapValue)))
            {
                int actual = new MemoryBlock(heapPtr, heap.Length).BinarySearch(values, offset);

                string heapSubstr = GetStringHeapValue(heapValue, offset);
                int expected = Array.BinarySearch(values, heapSubstr);

                Assert.Equal(expected, actual);
            }
        }
Пример #13
0
        /// <summary>
        /// Creates a metadata reader from the metadata stored at the given memory location.
        /// </summary>
        /// <remarks>
        /// The memory is owned by the caller and it must be kept memory alive and unmodified throughout the lifetime of the <see cref="MetadataReader"/>.
        /// Use <see cref="PEReaderExtensions.GetMetadataReader(PortableExecutable.PEReader, MetadataReaderOptions, MetadataStringDecoder)"/> to obtain 
        /// metadata from a PE image.
        /// </remarks>
        /// <exception cref="ArgumentOutOfRangeException"><paramref name="length"/> is not positive.</exception>
        /// <exception cref="ArgumentNullException"><paramref name="metadata"/> is null.</exception>
        /// <exception cref="ArgumentException">The encoding of <paramref name="utf8Decoder"/> is not <see cref="UTF8Encoding"/>.</exception>
        /// <exception cref="PlatformNotSupportedException">The current platform is big-endian.</exception>
        public unsafe MetadataReader(byte* metadata, int length, MetadataReaderOptions options, MetadataStringDecoder utf8Decoder)
        {
            // Do not throw here when length is 0. We'll throw BadImageFormatException later on, so that the caller doesn't need to 
            // worry about the image (stream) being empty and can handle all image errors by catching BadImageFormatException.
            if (length < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(length));
            }

            if (metadata == null)
            {
                throw new ArgumentNullException(nameof(metadata));
            }

            if (utf8Decoder == null)
            {
                utf8Decoder = MetadataStringDecoder.DefaultUTF8;
            }

            if (!(utf8Decoder.Encoding is UTF8Encoding))
            {
                throw new ArgumentException(SR.MetadataStringDecoderEncodingMustBeUtf8, nameof(utf8Decoder));
            }

            if (!BitConverter.IsLittleEndian)
            {
                Throw.LitteEndianArchitectureRequired();
            }

            this.Block = new MemoryBlock(metadata, length);

            _options = options;
            this.UTF8Decoder = utf8Decoder;

            var headerReader = new BlobReader(this.Block);
            this.ReadMetadataHeader(ref headerReader, out _versionString);
            _metadataKind = GetMetadataKind(_versionString);
            var streamHeaders = this.ReadStreamHeaders(ref headerReader);

            // storage header and stream headers:
            MemoryBlock metadataTableStream;
            MemoryBlock standalonePdbStream;
            this.InitializeStreamReaders(ref this.Block, streamHeaders, out _metadataStreamKind, out metadataTableStream, out standalonePdbStream);

            int[] externalTableRowCountsOpt;
            if (standalonePdbStream.Length > 0)
            {
                ReadStandalonePortablePdbStream(standalonePdbStream, out _debugMetadataHeader, out externalTableRowCountsOpt);
            }
            else
            {
                externalTableRowCountsOpt = null;
            }

            var tableReader = new BlobReader(metadataTableStream);

            HeapSizes heapSizes;
            int[] metadataTableRowCounts;
            this.ReadMetadataTableHeader(ref tableReader, out heapSizes, out metadataTableRowCounts, out _sortedTables);

            this.InitializeTableReaders(tableReader.GetMemoryBlockAt(0, tableReader.RemainingBytes), heapSizes, metadataTableRowCounts, externalTableRowCountsOpt);

            // This previously could occur in obfuscated assemblies but a check was added to prevent 
            // it getting to this point
            Debug.Assert(this.AssemblyTable.NumberOfRows <= 1);

            // Although the specification states that the module table will have exactly one row,
            // the native metadata reader would successfully read files containing more than one row.
            // Such files exist in the wild and may be produced by obfuscators.
            if (standalonePdbStream.Length == 0 && this.ModuleTable.NumberOfRows < 1)
            {
                throw new BadImageFormatException(SR.Format(SR.ModuleTableInvalidNumberOfRows, this.ModuleTable.NumberOfRows));
            }

            //  read 
            this.NamespaceCache = new NamespaceCache(this);

            if (_metadataKind != MetadataKind.Ecma335)
            {
                this.WinMDMscorlibRef = FindMscorlibAssemblyRefNoProjection();
            }
        }
Пример #14
0
        private void InitializeTableReaders(MemoryBlock metadataTablesMemoryBlock, HeapSizes heapSizes, int[] rowCounts, int[] externalRowCountsOpt)
        {
            // Size of reference tags in each table.
            this.TableRowCounts = rowCounts;

            // TODO (https://github.com/dotnet/corefx/issues/2061): 
            // Shouldn't XxxPtr table be always the same size or smaller than the corresponding Xxx table?

            // Compute ref sizes for tables that can have pointer tables
            int fieldRefSizeSorted = GetReferenceSize(rowCounts, TableIndex.FieldPtr) > SmallIndexSize ? LargeIndexSize : GetReferenceSize(rowCounts, TableIndex.Field);
            int methodRefSizeSorted = GetReferenceSize(rowCounts, TableIndex.MethodPtr) > SmallIndexSize ? LargeIndexSize : GetReferenceSize(rowCounts, TableIndex.MethodDef);
            int paramRefSizeSorted = GetReferenceSize(rowCounts, TableIndex.ParamPtr) > SmallIndexSize ? LargeIndexSize : GetReferenceSize(rowCounts, TableIndex.Param);
            int eventRefSizeSorted = GetReferenceSize(rowCounts, TableIndex.EventPtr) > SmallIndexSize ? LargeIndexSize : GetReferenceSize(rowCounts, TableIndex.Event);
            int propertyRefSizeSorted = GetReferenceSize(rowCounts, TableIndex.PropertyPtr) > SmallIndexSize ? LargeIndexSize : GetReferenceSize(rowCounts, TableIndex.Property);

            // Compute the coded token ref sizes
            int typeDefOrRefRefSize = ComputeCodedTokenSize(TypeDefOrRefTag.LargeRowSize, rowCounts, TypeDefOrRefTag.TablesReferenced);
            int hasConstantRefSize = ComputeCodedTokenSize(HasConstantTag.LargeRowSize, rowCounts, HasConstantTag.TablesReferenced);
            int hasCustomAttributeRefSize = ComputeCodedTokenSize(HasCustomAttributeTag.LargeRowSize, rowCounts, HasCustomAttributeTag.TablesReferenced);
            int hasFieldMarshalRefSize = ComputeCodedTokenSize(HasFieldMarshalTag.LargeRowSize, rowCounts, HasFieldMarshalTag.TablesReferenced);
            int hasDeclSecurityRefSize = ComputeCodedTokenSize(HasDeclSecurityTag.LargeRowSize, rowCounts, HasDeclSecurityTag.TablesReferenced);
            int memberRefParentRefSize = ComputeCodedTokenSize(MemberRefParentTag.LargeRowSize, rowCounts, MemberRefParentTag.TablesReferenced);
            int hasSemanticsRefSize = ComputeCodedTokenSize(HasSemanticsTag.LargeRowSize, rowCounts, HasSemanticsTag.TablesReferenced);
            int methodDefOrRefRefSize = ComputeCodedTokenSize(MethodDefOrRefTag.LargeRowSize, rowCounts, MethodDefOrRefTag.TablesReferenced);
            int memberForwardedRefSize = ComputeCodedTokenSize(MemberForwardedTag.LargeRowSize, rowCounts, MemberForwardedTag.TablesReferenced);
            int implementationRefSize = ComputeCodedTokenSize(ImplementationTag.LargeRowSize, rowCounts, ImplementationTag.TablesReferenced);
            int customAttributeTypeRefSize = ComputeCodedTokenSize(CustomAttributeTypeTag.LargeRowSize, rowCounts, CustomAttributeTypeTag.TablesReferenced);
            int resolutionScopeRefSize = ComputeCodedTokenSize(ResolutionScopeTag.LargeRowSize, rowCounts, ResolutionScopeTag.TablesReferenced);
            int typeOrMethodDefRefSize = ComputeCodedTokenSize(TypeOrMethodDefTag.LargeRowSize, rowCounts, TypeOrMethodDefTag.TablesReferenced);

            // Compute HeapRef Sizes
            int stringHeapRefSize = (heapSizes & HeapSizes.StringHeapLarge) == HeapSizes.StringHeapLarge ? LargeIndexSize : SmallIndexSize;
            int guidHeapRefSize = (heapSizes & HeapSizes.GuidHeapLarge) == HeapSizes.GuidHeapLarge ? LargeIndexSize : SmallIndexSize;
            int blobHeapRefSize = (heapSizes & HeapSizes.BlobHeapLarge) == HeapSizes.BlobHeapLarge ? LargeIndexSize : SmallIndexSize;

            // Populate the Table blocks
            int totalRequiredSize = 0;
            this.ModuleTable = new ModuleTableReader(rowCounts[(int)TableIndex.Module], stringHeapRefSize, guidHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ModuleTable.Block.Length;

            this.TypeRefTable = new TypeRefTableReader(rowCounts[(int)TableIndex.TypeRef], resolutionScopeRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.TypeRefTable.Block.Length;

            this.TypeDefTable = new TypeDefTableReader(rowCounts[(int)TableIndex.TypeDef], fieldRefSizeSorted, methodRefSizeSorted, typeDefOrRefRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.TypeDefTable.Block.Length;

            this.FieldPtrTable = new FieldPtrTableReader(rowCounts[(int)TableIndex.FieldPtr], GetReferenceSize(rowCounts, TableIndex.Field), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FieldPtrTable.Block.Length;

            this.FieldTable = new FieldTableReader(rowCounts[(int)TableIndex.Field], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FieldTable.Block.Length;

            this.MethodPtrTable = new MethodPtrTableReader(rowCounts[(int)TableIndex.MethodPtr], GetReferenceSize(rowCounts, TableIndex.MethodDef), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodPtrTable.Block.Length;

            this.MethodDefTable = new MethodTableReader(rowCounts[(int)TableIndex.MethodDef], paramRefSizeSorted, stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodDefTable.Block.Length;

            this.ParamPtrTable = new ParamPtrTableReader(rowCounts[(int)TableIndex.ParamPtr], GetReferenceSize(rowCounts, TableIndex.Param), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ParamPtrTable.Block.Length;

            this.ParamTable = new ParamTableReader(rowCounts[(int)TableIndex.Param], stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ParamTable.Block.Length;

            this.InterfaceImplTable = new InterfaceImplTableReader(rowCounts[(int)TableIndex.InterfaceImpl], IsDeclaredSorted(TableMask.InterfaceImpl), GetReferenceSize(rowCounts, TableIndex.TypeDef), typeDefOrRefRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.InterfaceImplTable.Block.Length;

            this.MemberRefTable = new MemberRefTableReader(rowCounts[(int)TableIndex.MemberRef], memberRefParentRefSize, stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MemberRefTable.Block.Length;

            this.ConstantTable = new ConstantTableReader(rowCounts[(int)TableIndex.Constant], IsDeclaredSorted(TableMask.Constant), hasConstantRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ConstantTable.Block.Length;

            this.CustomAttributeTable = new CustomAttributeTableReader(rowCounts[(int)TableIndex.CustomAttribute],
                                                                       IsDeclaredSorted(TableMask.CustomAttribute),
                                                                       hasCustomAttributeRefSize,
                                                                       customAttributeTypeRefSize,
                                                                       blobHeapRefSize,
                                                                       metadataTablesMemoryBlock,
                                                                       totalRequiredSize);
            totalRequiredSize += this.CustomAttributeTable.Block.Length;

            this.FieldMarshalTable = new FieldMarshalTableReader(rowCounts[(int)TableIndex.FieldMarshal], IsDeclaredSorted(TableMask.FieldMarshal), hasFieldMarshalRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FieldMarshalTable.Block.Length;

            this.DeclSecurityTable = new DeclSecurityTableReader(rowCounts[(int)TableIndex.DeclSecurity], IsDeclaredSorted(TableMask.DeclSecurity), hasDeclSecurityRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.DeclSecurityTable.Block.Length;

            this.ClassLayoutTable = new ClassLayoutTableReader(rowCounts[(int)TableIndex.ClassLayout], IsDeclaredSorted(TableMask.ClassLayout), GetReferenceSize(rowCounts, TableIndex.TypeDef), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ClassLayoutTable.Block.Length;

            this.FieldLayoutTable = new FieldLayoutTableReader(rowCounts[(int)TableIndex.FieldLayout], IsDeclaredSorted(TableMask.FieldLayout), GetReferenceSize(rowCounts, TableIndex.Field), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FieldLayoutTable.Block.Length;

            this.StandAloneSigTable = new StandAloneSigTableReader(rowCounts[(int)TableIndex.StandAloneSig], blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.StandAloneSigTable.Block.Length;

            this.EventMapTable = new EventMapTableReader(rowCounts[(int)TableIndex.EventMap], GetReferenceSize(rowCounts, TableIndex.TypeDef), eventRefSizeSorted, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.EventMapTable.Block.Length;

            this.EventPtrTable = new EventPtrTableReader(rowCounts[(int)TableIndex.EventPtr], GetReferenceSize(rowCounts, TableIndex.Event), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.EventPtrTable.Block.Length;

            this.EventTable = new EventTableReader(rowCounts[(int)TableIndex.Event], typeDefOrRefRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.EventTable.Block.Length;

            this.PropertyMapTable = new PropertyMapTableReader(rowCounts[(int)TableIndex.PropertyMap], GetReferenceSize(rowCounts, TableIndex.TypeDef), propertyRefSizeSorted, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.PropertyMapTable.Block.Length;

            this.PropertyPtrTable = new PropertyPtrTableReader(rowCounts[(int)TableIndex.PropertyPtr], GetReferenceSize(rowCounts, TableIndex.Property), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.PropertyPtrTable.Block.Length;

            this.PropertyTable = new PropertyTableReader(rowCounts[(int)TableIndex.Property], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.PropertyTable.Block.Length;

            this.MethodSemanticsTable = new MethodSemanticsTableReader(rowCounts[(int)TableIndex.MethodSemantics], IsDeclaredSorted(TableMask.MethodSemantics), GetReferenceSize(rowCounts, TableIndex.MethodDef), hasSemanticsRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodSemanticsTable.Block.Length;

            this.MethodImplTable = new MethodImplTableReader(rowCounts[(int)TableIndex.MethodImpl], IsDeclaredSorted(TableMask.MethodImpl), GetReferenceSize(rowCounts, TableIndex.TypeDef), methodDefOrRefRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodImplTable.Block.Length;

            this.ModuleRefTable = new ModuleRefTableReader(rowCounts[(int)TableIndex.ModuleRef], stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ModuleRefTable.Block.Length;

            this.TypeSpecTable = new TypeSpecTableReader(rowCounts[(int)TableIndex.TypeSpec], blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.TypeSpecTable.Block.Length;

            this.ImplMapTable = new ImplMapTableReader(rowCounts[(int)TableIndex.ImplMap], IsDeclaredSorted(TableMask.ImplMap), GetReferenceSize(rowCounts, TableIndex.ModuleRef), memberForwardedRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ImplMapTable.Block.Length;

            this.FieldRvaTable = new FieldRVATableReader(rowCounts[(int)TableIndex.FieldRva], IsDeclaredSorted(TableMask.FieldRva), GetReferenceSize(rowCounts, TableIndex.Field), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FieldRvaTable.Block.Length;

            this.EncLogTable = new EnCLogTableReader(rowCounts[(int)TableIndex.EncLog], metadataTablesMemoryBlock, totalRequiredSize, _metadataStreamKind);
            totalRequiredSize += this.EncLogTable.Block.Length;

            this.EncMapTable = new EnCMapTableReader(rowCounts[(int)TableIndex.EncMap], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.EncMapTable.Block.Length;

            this.AssemblyTable = new AssemblyTableReader(rowCounts[(int)TableIndex.Assembly], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.AssemblyTable.Block.Length;

            this.AssemblyProcessorTable = new AssemblyProcessorTableReader(rowCounts[(int)TableIndex.AssemblyProcessor], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.AssemblyProcessorTable.Block.Length;

            this.AssemblyOSTable = new AssemblyOSTableReader(rowCounts[(int)TableIndex.AssemblyOS], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.AssemblyOSTable.Block.Length;

            this.AssemblyRefTable = new AssemblyRefTableReader(rowCounts[(int)TableIndex.AssemblyRef], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize, _metadataKind);
            totalRequiredSize += this.AssemblyRefTable.Block.Length;

            this.AssemblyRefProcessorTable = new AssemblyRefProcessorTableReader(rowCounts[(int)TableIndex.AssemblyRefProcessor], GetReferenceSize(rowCounts, TableIndex.AssemblyRef), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.AssemblyRefProcessorTable.Block.Length;

            this.AssemblyRefOSTable = new AssemblyRefOSTableReader(rowCounts[(int)TableIndex.AssemblyRefOS], GetReferenceSize(rowCounts, TableIndex.AssemblyRef), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.AssemblyRefOSTable.Block.Length;

            this.FileTable = new FileTableReader(rowCounts[(int)TableIndex.File], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FileTable.Block.Length;

            this.ExportedTypeTable = new ExportedTypeTableReader(rowCounts[(int)TableIndex.ExportedType], implementationRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ExportedTypeTable.Block.Length;

            this.ManifestResourceTable = new ManifestResourceTableReader(rowCounts[(int)TableIndex.ManifestResource], implementationRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ManifestResourceTable.Block.Length;

            this.NestedClassTable = new NestedClassTableReader(rowCounts[(int)TableIndex.NestedClass], IsDeclaredSorted(TableMask.NestedClass), GetReferenceSize(rowCounts, TableIndex.TypeDef), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.NestedClassTable.Block.Length;

            this.GenericParamTable = new GenericParamTableReader(rowCounts[(int)TableIndex.GenericParam], IsDeclaredSorted(TableMask.GenericParam), typeOrMethodDefRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.GenericParamTable.Block.Length;

            this.MethodSpecTable = new MethodSpecTableReader(rowCounts[(int)TableIndex.MethodSpec], methodDefOrRefRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodSpecTable.Block.Length;

            this.GenericParamConstraintTable = new GenericParamConstraintTableReader(rowCounts[(int)TableIndex.GenericParamConstraint], IsDeclaredSorted(TableMask.GenericParamConstraint), GetReferenceSize(rowCounts, TableIndex.GenericParam), typeDefOrRefRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.GenericParamConstraintTable.Block.Length;

            // debug tables:
            // Type-system metadata tables may be stored in a separate (external) metadata file.
            // We need to use the row counts of the external tables when referencing them.
            // Debug tables are local to the current metadata image and type system metadata tables are external and precede all debug tables.
            var combinedRowCounts = (externalRowCountsOpt != null) ? CombineRowCounts(rowCounts, externalRowCountsOpt, firstLocalTableIndex: TableIndex.Document) : rowCounts;

            int methodRefSizeCombined = GetReferenceSize(combinedRowCounts, TableIndex.MethodDef);
            int hasCustomDebugInformationRefSizeCombined = ComputeCodedTokenSize(HasCustomDebugInformationTag.LargeRowSize, combinedRowCounts, HasCustomDebugInformationTag.TablesReferenced);

            this.DocumentTable = new DocumentTableReader(rowCounts[(int)TableIndex.Document], guidHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.DocumentTable.Block.Length;

            this.MethodDebugInformationTable = new MethodDebugInformationTableReader(rowCounts[(int)TableIndex.MethodDebugInformation], GetReferenceSize(rowCounts, TableIndex.Document), blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodDebugInformationTable.Block.Length;

            this.LocalScopeTable = new LocalScopeTableReader(rowCounts[(int)TableIndex.LocalScope], IsDeclaredSorted(TableMask.LocalScope), methodRefSizeCombined, GetReferenceSize(rowCounts, TableIndex.ImportScope), GetReferenceSize(rowCounts, TableIndex.LocalVariable), GetReferenceSize(rowCounts, TableIndex.LocalConstant), metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.LocalScopeTable.Block.Length;

            this.LocalVariableTable = new LocalVariableTableReader(rowCounts[(int)TableIndex.LocalVariable], stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.LocalVariableTable.Block.Length;

            this.LocalConstantTable = new LocalConstantTableReader(rowCounts[(int)TableIndex.LocalConstant], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.LocalConstantTable.Block.Length;

            this.ImportScopeTable = new ImportScopeTableReader(rowCounts[(int)TableIndex.ImportScope], GetReferenceSize(rowCounts, TableIndex.ImportScope), blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ImportScopeTable.Block.Length;

            this.StateMachineMethodTable = new StateMachineMethodTableReader(rowCounts[(int)TableIndex.StateMachineMethod], IsDeclaredSorted(TableMask.StateMachineMethod), methodRefSizeCombined, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.StateMachineMethodTable.Block.Length;

            this.CustomDebugInformationTable = new CustomDebugInformationTableReader(rowCounts[(int)TableIndex.CustomDebugInformation], IsDeclaredSorted(TableMask.CustomDebugInformation), hasCustomDebugInformationRefSizeCombined, guidHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.CustomDebugInformationTable.Block.Length;

            if (totalRequiredSize > metadataTablesMemoryBlock.Length)
            {
                throw new BadImageFormatException(SR.MetadataTablesTooSmall);
            }
        }
Пример #15
0
        // internal for testing
        internal static void ReadStandalonePortablePdbStream(MemoryBlock block, out DebugMetadataHeader debugMetadataHeader, out int[] externalTableRowCounts)
        {
            var reader = new BlobReader(block);

            const int PdbIdSize = 20;
            byte[] pdbId = reader.ReadBytes(PdbIdSize);

            // ECMA-335 15.4.1.2:
            // The entry point to an application shall be static.
            // This entry point method can be a global method or it can appear inside a type. 
            // The entry point method shall either accept no arguments or a vector of strings.
            // The return type of the entry point method shall be void, int32, or unsigned int32. 
            // The entry point method cannot be defined in a generic class.
            uint entryPointToken = reader.ReadUInt32();
            int entryPointRowId = (int)(entryPointToken & TokenTypeIds.RIDMask);
            if (entryPointToken != 0 && ((entryPointToken & TokenTypeIds.TypeMask) != TokenTypeIds.MethodDef || entryPointRowId == 0))
            {
                throw new BadImageFormatException(string.Format(SR.InvalidEntryPointToken, entryPointToken));
            }

            ulong externalTableMask = reader.ReadUInt64();

            // EnC & Ptr tables can't be referenced from standalone PDB metadata:
            const ulong validTables = (ulong)TableMask.ValidPortablePdbExternalTables;

            if ((externalTableMask & ~validTables) != 0)
            {
                throw new BadImageFormatException(string.Format(SR.UnknownTables, (TableMask)externalTableMask));
            }

            externalTableRowCounts = ReadMetadataTableRowCounts(ref reader, externalTableMask);

            debugMetadataHeader = new DebugMetadataHeader(
                ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref pdbId),
                MethodDefinitionHandle.FromRowId(entryPointRowId));
        }
Пример #16
0
        internal DeclSecurityTableReader(
            int numberOfRows,
            bool declaredSorted,
            int hasDeclSecurityRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset
        )
        {
            this.NumberOfRows = numberOfRows;
            _IsHasDeclSecurityRefSizeSmall = hasDeclSecurityRefSize == 2;
            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
            _ActionOffset = 0;
            _ParentOffset = _ActionOffset + sizeof(UInt16);
            _PermissionSetOffset = _ParentOffset + hasDeclSecurityRefSize;
            this.RowSize = _PermissionSetOffset + blobHeapRefSize;
            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, (int)(this.RowSize * numberOfRows));

            if (!declaredSorted && !CheckSorted())
            {
                Throw.TableNotSorted(TableIndex.DeclSecurity);
            }
        }
Пример #17
0
        internal FieldMarshalTableReader(
            int numberOfRows,
            bool declaredSorted,
            int hasFieldMarshalRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset
        )
        {
            this.NumberOfRows = numberOfRows;
            _IsHasFieldMarshalRefSizeSmall = hasFieldMarshalRefSize == 2;
            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
            _ParentOffset = 0;
            _NativeTypeOffset = _ParentOffset + hasFieldMarshalRefSize;
            this.RowSize = _NativeTypeOffset + blobHeapRefSize;
            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, this.RowSize * numberOfRows);

            if (!declaredSorted && !CheckSorted())
            {
                Throw.TableNotSorted(TableIndex.FieldMarshal);
            }
        }
Пример #18
0
 internal TypeRefTableReader(
     int numberOfRows,
     int resolutionScopeRefSize,
     int stringHeapRefSize,
     MemoryBlock containingBlock,
     int containingBlockOffset
 )
 {
     this.NumberOfRows = numberOfRows;
     _IsResolutionScopeRefSizeSmall = resolutionScopeRefSize == 2;
     _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
     _ResolutionScopeOffset = 0;
     _NameOffset = _ResolutionScopeOffset + resolutionScopeRefSize;
     _NamespaceOffset = _NameOffset + stringHeapRefSize;
     this.RowSize = _NamespaceOffset + stringHeapRefSize;
     this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, (int)(this.RowSize * numberOfRows));
 }
Пример #19
0
        internal CustomAttributeTableReader(
            int numberOfRows,
            bool declaredSorted,
            int hasCustomAttributeRefSize,
            int customAttributeTypeRefSize,
            int blobHeapRefSize,
            MemoryBlock containingBlock,
            int containingBlockOffset
        )
        {
            this.NumberOfRows = numberOfRows;
            _IsHasCustomAttributeRefSizeSmall = hasCustomAttributeRefSize == 2;
            _IsCustomAttributeTypeRefSizeSmall = customAttributeTypeRefSize == 2;
            _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
            _ParentOffset = 0;
            _TypeOffset = _ParentOffset + hasCustomAttributeRefSize;
            _ValueOffset = _TypeOffset + customAttributeTypeRefSize;
            this.RowSize = _ValueOffset + blobHeapRefSize;
            this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, (int)(this.RowSize * numberOfRows));
            this.PtrTable = null;

            if (!declaredSorted && !CheckSorted())
            {
                this.PtrTable = this.Block.BuildPtrTable(
                    numberOfRows,
                    this.RowSize,
                    _ParentOffset,
                    _IsHasCustomAttributeRefSizeSmall);
            }
        }
Пример #20
0
        private unsafe void TestComparisons(string heapValue, int offset, string value, bool unicode = false)
        {
            byte[] heap;
            MetadataStringDecoder decoder = MetadataStringDecoder.DefaultUTF8;

            fixed (byte* heapPtr = (heap = Encoding.UTF8.GetBytes(heapValue)))
            {
                var block = new MemoryBlock(heapPtr, heap.Length);
                string heapSubstr = GetStringHeapValue(heapValue, offset);

                // compare:
                if (!unicode)
                {
                    int actualCmp = block.CompareUtf8NullTerminatedStringWithAsciiString(offset, value);
                    int expectedCmp = StringComparer.Ordinal.Compare(heapSubstr, value);
                    Assert.Equal(Math.Sign(expectedCmp), Math.Sign(actualCmp));
                }

                // equals:
                bool actualEq = block.Utf8NullTerminatedEquals(offset, value, decoder);
                bool expectedEq = StringComparer.Ordinal.Equals(heapSubstr, value);
                Assert.Equal(expectedEq, actualEq);

                // starts with:
                bool actualSW = block.Utf8NullTerminatedStartsWith(offset, value, decoder);
                bool expectedSW = heapSubstr.StartsWith(value, StringComparison.Ordinal);
                Assert.Equal(actualSW, expectedSW);
            }
        }
Пример #21
0
        public unsafe void ComparisonToInvalidByteSequenceMatchesFallback()
        {
            MetadataStringDecoder decoder = MetadataStringDecoder.DefaultUTF8;

            // dangling lead byte
            byte[] buffer;
            fixed (byte* ptr = (buffer = new byte[] { 0xC0 }))
            {
                var block = new MemoryBlock(ptr, buffer.Length);
                Assert.False(block.Utf8NullTerminatedStartsWith(0, new string((char)0xC0, 1), decoder));
                Assert.False(block.Utf8NullTerminatedEquals(0, new string((char)0xC0, 1), decoder));
                Assert.True(block.Utf8NullTerminatedStartsWith(0, "\uFFFD", decoder));
                Assert.True(block.Utf8NullTerminatedEquals(0, "\uFFFD", decoder));
            }

            // overlong encoding
            fixed (byte* ptr = (buffer = new byte[] { (byte)'a', 0xC0, 0xAF, (byte)'b', 0x0 }))
            {
                var block = new MemoryBlock(ptr, buffer.Length);
                Assert.False(block.Utf8NullTerminatedStartsWith(0, "a\\", decoder));
                Assert.False(block.Utf8NullTerminatedEquals(0, "a\\b", decoder));
                Assert.True(block.Utf8NullTerminatedStartsWith(0, "a\uFFFD", decoder));
                Assert.True(block.Utf8NullTerminatedEquals(0, "a\uFFFD\uFFFDb", decoder));
            }
        }
Пример #22
0
 private unsafe static EnCMapTableReader CreateEncMapTable(int[] tokens)
 {
     GCHandle handle = GCHandle.Alloc(tokens, GCHandleType.Pinned);
     var block = new MemoryBlock((byte*)handle.AddrOfPinnedObject(), tokens.Length * sizeof(uint));
     return new EnCMapTableReader(tokens.Length, block, containingBlockOffset: 0);
 }
Пример #23
0
        public unsafe void BuildPtrTable_LargeRefs()
        {
            const int rowSize = 6;
            const int secondColumnOffset = 2;

            var table = new byte[]
            {
                0xAA, 0xAA, 0x10, 0x00, 0x05, 0x00,
                0xBB, 0xBB, 0x10, 0x00, 0x04, 0x00,
                0xCC, 0xCC, 0x10, 0x00, 0x02, 0x01,
                0xDD, 0xDD, 0x10, 0x00, 0x02, 0x00,
                0xEE, 0xEE, 0x10, 0x00, 0x01, 0x01,
            };

            int rowCount = table.Length / rowSize;

            fixed (byte* tablePtr = table)
            {
                var block = new MemoryBlock(tablePtr, table.Length);

                Assert.Equal(0x00040010, block.PeekReference(8, smallRefSize: false));

                var actual = block.BuildPtrTable(rowCount, rowSize, secondColumnOffset, isReferenceSmall: false);
                var expected = new int[] { 4, 2, 1, 5, 3 };
                Assert.Equal(expected, actual);
            }
        }
Пример #24
0
        private void InitializeStreamReaders(ref MemoryBlock metadataRoot, StreamHeader[] streamHeaders, out MemoryBlock metadataTableStream)
        {
            metadataTableStream = default(MemoryBlock);

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

                        this.StringStream = new StringStreamReader(metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size), this.metadataKind);
                        break;

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

                        this.BlobStream = new BlobStreamReader(metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size), this.metadataKind);
                        break;

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

                        this.GuidStream = new GuidStreamReader(metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size));
                        break;

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

                        this.UserStringStream = new UserStringStreamReader(metadataRoot.GetMemoryBlockAt((int)streamHeader.Offset, streamHeader.Size));
                        break;

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

                        this.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(MetadataResources.NotEnoughSpaceForMetadataStream);
                        }

                        this.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(MetadataResources.NotEnoughSpaceForMetadataStream);
                        }

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

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

            if (IsMinimalDelta && metadataStreamKind != MetadataStreamKind.Uncompressed)
            {
                throw new BadImageFormatException(MetadataResources.InvalidMetadataStreamFormat);
            }
        }
Пример #25
0
        public unsafe void ValidatePeekReferenceSize()
        {
            byte[] buffer = new byte[8] { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01 };
            fixed (byte* bufferPtr = buffer)
            {
                var block = new MemoryBlock(bufferPtr, buffer.Length);

                // small ref size always fits in 16 bits
                Assert.Equal(0xFFFF, block.PeekReference(0, smallRefSize: true));
                Assert.Equal(0xFFFF, block.PeekReference(4, smallRefSize: true));
                Assert.Equal(0xFFFFU, block.PeekTaggedReference(0, smallRefSize: true));
                Assert.Equal(0xFFFFU, block.PeekTaggedReference(4, smallRefSize: true));
                Assert.Equal(0x01FFU, block.PeekTaggedReference(6, smallRefSize: true));

                // large ref size throws on > RIDMask when tagged variant is not used.
                Assert.Throws<BadImageFormatException>(() => block.PeekReference(0, smallRefSize: false));
                Assert.Throws<BadImageFormatException>(() => block.PeekReference(4, smallRefSize: false));

                // large ref size does not throw when Tagged variant is used.
                Assert.Equal(0xFFFFFFFFU, block.PeekTaggedReference(0, smallRefSize: false));
                Assert.Equal(0x01FFFFFFU, block.PeekTaggedReference(4, smallRefSize: false));

                // bounds check applies in all cases
                Assert.Throws<BadImageFormatException>(() => block.PeekReference(7, smallRefSize: true));
                Assert.Throws<BadImageFormatException>(() => block.PeekReference(5, smallRefSize: false));
            }
        }
Пример #26
0
 internal MemberRefTableReader(
     int numberOfRows,
     int memberRefParentRefSize,
     int stringHeapRefSize,
     int blobHeapRefSize,
     MemoryBlock containingBlock,
     int containingBlockOffset
 )
 {
     this.NumberOfRows = numberOfRows;
     _IsMemberRefParentRefSizeSmall = memberRefParentRefSize == 2;
     _IsStringHeapRefSizeSmall = stringHeapRefSize == 2;
     _IsBlobHeapRefSizeSmall = blobHeapRefSize == 2;
     _ClassOffset = 0;
     _NameOffset = _ClassOffset + memberRefParentRefSize;
     _SignatureOffset = _NameOffset + stringHeapRefSize;
     this.RowSize = _SignatureOffset + blobHeapRefSize;
     this.Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, (int)(this.RowSize * numberOfRows));
 }
Пример #27
0
        /// <summary>
        /// Creates a metadata reader from the metadata stored at the given memory location.
        /// </summary>
        /// <remarks>
        /// The memory is owned by the caller and it must be kept memory alive and unmodified throughout the lifetime of the <see cref="MetadataReader"/>.
        /// Use <see cref="PEReaderExtensions.GetMetadataReader(PortableExecutable.PEReader, MetadataReaderOptions, MetadataStringDecoder)"/> to obtain 
        /// metadata from a PE image.
        /// </remarks>
        public unsafe MetadataReader(byte* metadata, int length, MetadataReaderOptions options, MetadataStringDecoder utf8Decoder)
        {
            if (length <= 0)
            {
                throw new ArgumentOutOfRangeException("length");
            }

            if (metadata == null)
            {
                throw new ArgumentNullException("metadata");
            }

            if (utf8Decoder == null)
            {
                utf8Decoder = MetadataStringDecoder.DefaultUTF8;
            }

            if (!(utf8Decoder.Encoding is UTF8Encoding))
            {
                throw new ArgumentException(MetadataResources.MetadataStringDecoderEncodingMustBeUtf8, "utf8Decoder");
            }

            if (!BitConverter.IsLittleEndian)
            {
                throw new PlatformNotSupportedException(MetadataResources.LitteEndianArchitectureRequired);
            }

            this.Block = new MemoryBlock(metadata, length);

            this.options = options;
            this.utf8Decoder = utf8Decoder;

            BlobReader memReader = new BlobReader(this.Block);

            this.ReadMetadataHeader(ref memReader);

            // storage header and stream headers:
            MemoryBlock metadataTableStream;
            var streamHeaders = this.ReadStreamHeaders(ref memReader);
            this.InitializeStreamReaders(ref this.Block, streamHeaders, out metadataTableStream);

            memReader = new BlobReader(metadataTableStream);

            uint[] metadataTableRowCounts;
            this.ReadMetadataTableHeader(ref memReader, out metadataTableRowCounts);
            this.InitializeTableReaders(memReader.GetMemoryBlockAt(0, memReader.RemainingBytes), metadataTableRowCounts);

            // This previously could occur in obfuscated assemblies but a check was added to prevent
            // it getting to this point
            Debug.Assert(this.AssemblyTable.NumberOfRows <= 1);

            // Although the specification states that the module table will have exactly one row,
            // the native metadata reader would successfully read files containing more than one row.
            // Such files exist in the wild and may be produced by obfuscators.
            if (this.ModuleTable.NumberOfRows < 1)
            {
                throw new BadImageFormatException(string.Format(MetadataResources.ModuleTableInvalidNumberOfRows, this.ModuleTable.NumberOfRows));
            }

            //  read
            this.namespaceCache = new NamespaceCache(this);

            if (this.metadataKind != MetadataKind.Ecma335)
            {
                this.WinMDMscorlibRef = FindMscorlibAssemblyRefNoProjection();
            }
        }
Пример #28
0
        public unsafe void ReadFromMemoryBlock()
        {
            byte[] buffer = new byte[4] { 0, 1, 0, 2 };
            fixed (byte* bufferPtr = buffer)
            {
                var block = new MemoryBlock(bufferPtr, buffer.Length);

                Assert.Throws<BadImageFormatException>(() => block.PeekUInt32(Int32.MaxValue));
                Assert.Throws<BadImageFormatException>(() => block.PeekUInt32(-1));
                Assert.Throws<BadImageFormatException>(() => block.PeekUInt32(Int32.MinValue));
                Assert.Throws<BadImageFormatException>(() => block.PeekUInt32(4));
                Assert.Throws<BadImageFormatException>(() => block.PeekUInt32(1));
                Assert.Equal(0x02000100U, block.PeekUInt32(0));

                Assert.Throws<BadImageFormatException>(() => block.PeekUInt16(Int32.MaxValue));
                Assert.Throws<BadImageFormatException>(() => block.PeekUInt16(-1));
                Assert.Throws<BadImageFormatException>(() => block.PeekUInt16(Int32.MinValue));
                Assert.Throws<BadImageFormatException>(() => block.PeekUInt16(4));
                Assert.Equal(0x0200, block.PeekUInt16(2));

                int bytesRead;

                MetadataStringDecoder stringDecoder = MetadataStringDecoder.DefaultUTF8;
                Assert.Throws<BadImageFormatException>(() => block.PeekUtf8NullTerminated(Int32.MaxValue, null, stringDecoder, out bytesRead));
                Assert.Throws<BadImageFormatException>(() => block.PeekUtf8NullTerminated(-1, null, stringDecoder, out bytesRead));
                Assert.Throws<BadImageFormatException>(() => block.PeekUtf8NullTerminated(Int32.MinValue, null, stringDecoder, out bytesRead));
                Assert.Throws<BadImageFormatException>(() => block.PeekUtf8NullTerminated(5, null, stringDecoder, out bytesRead));

                Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(-1, 1));
                Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(1, -1));
                Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(0, -1));
                Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(-1, 0));
                Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(-Int32.MaxValue, Int32.MaxValue));
                Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(Int32.MaxValue, -Int32.MaxValue));
                Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(Int32.MaxValue, Int32.MaxValue));
                Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(block.Length, -1));
                Assert.Throws<BadImageFormatException>(() => block.GetMemoryBlockAt(-1, block.Length));


                Assert.Equal("\u0001", block.PeekUtf8NullTerminated(1, null, stringDecoder, out bytesRead));
                Assert.Equal(bytesRead, 2);

                Assert.Equal("\u0002", block.PeekUtf8NullTerminated(3, null, stringDecoder, out bytesRead));
                Assert.Equal(bytesRead, 1);

                Assert.Equal("", block.PeekUtf8NullTerminated(4, null, stringDecoder, out bytesRead));
                Assert.Equal(bytesRead, 0);

                byte[] helloPrefix = Encoding.UTF8.GetBytes("Hello");

                Assert.Equal("Hello\u0001", block.PeekUtf8NullTerminated(1, helloPrefix, stringDecoder, out bytesRead));
                Assert.Equal(bytesRead, 2);

                Assert.Equal("Hello\u0002", block.PeekUtf8NullTerminated(3, helloPrefix, stringDecoder, out bytesRead));
                Assert.Equal(bytesRead, 1);

                Assert.Equal("Hello", block.PeekUtf8NullTerminated(4, helloPrefix, stringDecoder, out bytesRead));
                Assert.Equal(bytesRead, 0);
            }
        }
Пример #29
0
        private void InitializeTableReaders(MemoryBlock metadataTablesMemoryBlock, uint[] compressedRowCounts)
        {
            // Only sizes of tables present in metadata are recorded in rowCountCompressedArray.
            // This array contains a slot for each possible table, not just those that are present in the metadata.
            uint[] rowCounts = new uint[TableIndexExtensions.Count];

            // Size of reference tags in each table.
            int[] referenceSizes = new int[TableIndexExtensions.Count];

            ulong validTables = (ulong)this.MetadataTableHeader.ValidTables;
            int compressedRowCountIndex = 0;
            for (int i = 0; i < TableIndexExtensions.Count; i++)
            {
                bool fitsSmall;

                if ((validTables & 1UL) != 0)
                {
                    uint rowCount = compressedRowCounts[compressedRowCountIndex++];
                    rowCounts[i] = rowCount;
                    fitsSmall = rowCount < MetadataStreamConstants.LargeTableRowCount;
                }
                else
                {
                    fitsSmall = true;
                }

                referenceSizes[i] = (fitsSmall && !IsMinimalDelta) ? SmallIndexSize : LargeIndexSize;
                validTables >>= 1;
            }

            this.TableRowCounts = rowCounts;

            // Compute ref sizes for tables that can have pointer tables for it
            int fieldRefSize = referenceSizes[(int)TableIndex.FieldPtr] > SmallIndexSize ? LargeIndexSize : referenceSizes[(int)TableIndex.Field];
            int methodRefSize = referenceSizes[(int)TableIndex.MethodPtr] > SmallIndexSize ? LargeIndexSize : referenceSizes[(int)TableIndex.MethodDef];
            int paramRefSize = referenceSizes[(int)TableIndex.ParamPtr] > SmallIndexSize ? LargeIndexSize : referenceSizes[(int)TableIndex.Param];
            int eventRefSize = referenceSizes[(int)TableIndex.EventPtr] > SmallIndexSize ? LargeIndexSize : referenceSizes[(int)TableIndex.Event];
            int propertyRefSize = referenceSizes[(int)TableIndex.PropertyPtr] > SmallIndexSize ? LargeIndexSize : referenceSizes[(int)TableIndex.Property];

            // Compute the coded token ref sizes
            int typeDefOrRefRefSize = ComputeCodedTokenSize(TypeDefOrRefTag.LargeRowSize, rowCounts, TypeDefOrRefTag.TablesReferenced);
            int hasConstantRefSize = ComputeCodedTokenSize(HasConstantTag.LargeRowSize, rowCounts, HasConstantTag.TablesReferenced);
            int hasCustomAttributeRefSize = ComputeCodedTokenSize(HasCustomAttributeTag.LargeRowSize, rowCounts, HasCustomAttributeTag.TablesReferenced);
            int hasFieldMarshalRefSize = ComputeCodedTokenSize(HasFieldMarshalTag.LargeRowSize, rowCounts, HasFieldMarshalTag.TablesReferenced);
            int hasDeclSecurityRefSize = ComputeCodedTokenSize(HasDeclSecurityTag.LargeRowSize, rowCounts, HasDeclSecurityTag.TablesReferenced);
            int memberRefParentRefSize = ComputeCodedTokenSize(MemberRefParentTag.LargeRowSize, rowCounts, MemberRefParentTag.TablesReferenced);
            int hasSemanticsRefSize = ComputeCodedTokenSize(HasSemanticsTag.LargeRowSize, rowCounts, HasSemanticsTag.TablesReferenced);
            int methodDefOrRefRefSize = ComputeCodedTokenSize(MethodDefOrRefTag.LargeRowSize, rowCounts, MethodDefOrRefTag.TablesReferenced);
            int memberForwardedRefSize = ComputeCodedTokenSize(MemberForwardedTag.LargeRowSize, rowCounts, MemberForwardedTag.TablesReferenced);
            int implementationRefSize = ComputeCodedTokenSize(ImplementationTag.LargeRowSize, rowCounts, ImplementationTag.TablesReferenced);
            int customAttributeTypeRefSize = ComputeCodedTokenSize(CustomAttributeTypeTag.LargeRowSize, rowCounts, CustomAttributeTypeTag.TablesReferenced);
            int resolutionScopeRefSize = ComputeCodedTokenSize(ResolutionScopeTag.LargeRowSize, rowCounts, ResolutionScopeTag.TablesReferenced);
            int typeOrMethodDefRefSize = ComputeCodedTokenSize(TypeOrMethodDefTag.LargeRowSize, rowCounts, TypeOrMethodDefTag.TablesReferenced);

            // Compute HeapRef Sizes
            int stringHeapRefSize = (this.MetadataTableHeader.HeapSizeFlags & HeapSizeFlag.StringHeapLarge) == HeapSizeFlag.StringHeapLarge ? LargeIndexSize : SmallIndexSize;
            int guidHeapRefSize = (this.MetadataTableHeader.HeapSizeFlags & HeapSizeFlag.GuidHeapLarge) == HeapSizeFlag.GuidHeapLarge ? LargeIndexSize : SmallIndexSize;
            int blobHeapRefSize = (this.MetadataTableHeader.HeapSizeFlags & HeapSizeFlag.BlobHeapLarge) == HeapSizeFlag.BlobHeapLarge ? LargeIndexSize : SmallIndexSize;

            // Populate the Table blocks
            int totalRequiredSize = 0;
            this.ModuleTable = new ModuleTableReader(rowCounts[(int)TableIndex.Module], stringHeapRefSize, guidHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ModuleTable.Block.Length;

            this.TypeRefTable = new TypeRefTableReader(rowCounts[(int)TableIndex.TypeRef], resolutionScopeRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.TypeRefTable.Block.Length;

            this.TypeDefTable = new TypeDefTableReader(rowCounts[(int)TableIndex.TypeDef], fieldRefSize, methodRefSize, typeDefOrRefRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.TypeDefTable.Block.Length;

            this.FieldPtrTable = new FieldPtrTableReader(rowCounts[(int)TableIndex.FieldPtr], referenceSizes[(int)TableIndex.Field], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FieldPtrTable.Block.Length;

            this.FieldTable = new FieldTableReader(rowCounts[(int)TableIndex.Field], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FieldTable.Block.Length;

            this.MethodPtrTable = new MethodPtrTableReader(rowCounts[(int)TableIndex.MethodPtr], referenceSizes[(int)TableIndex.MethodDef], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodPtrTable.Block.Length;

            this.MethodDefTable = new MethodTableReader(rowCounts[(int)TableIndex.MethodDef], paramRefSize, stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodDefTable.Block.Length;

            this.ParamPtrTable = new ParamPtrTableReader(rowCounts[(int)TableIndex.ParamPtr], referenceSizes[(int)TableIndex.Param], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ParamPtrTable.Block.Length;

            this.ParamTable = new ParamTableReader(rowCounts[(int)TableIndex.Param], stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ParamTable.Block.Length;

            this.InterfaceImplTable = new InterfaceImplTableReader(rowCounts[(int)TableIndex.InterfaceImpl], IsDeclaredSorted(TableMask.InterfaceImpl), referenceSizes[(int)TableIndex.TypeDef], typeDefOrRefRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.InterfaceImplTable.Block.Length;

            this.MemberRefTable = new MemberRefTableReader(rowCounts[(int)TableIndex.MemberRef], memberRefParentRefSize, stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MemberRefTable.Block.Length;

            this.ConstantTable = new ConstantTableReader(rowCounts[(int)TableIndex.Constant], IsDeclaredSorted(TableMask.Constant), hasConstantRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ConstantTable.Block.Length;

            this.CustomAttributeTable = new CustomAttributeTableReader(rowCounts[(int)TableIndex.CustomAttribute],
                                                                       IsDeclaredSorted(TableMask.CustomAttribute),
                                                                       hasCustomAttributeRefSize,
                                                                       customAttributeTypeRefSize,
                                                                       blobHeapRefSize,
                                                                       metadataTablesMemoryBlock,
                                                                       totalRequiredSize);
            totalRequiredSize += this.CustomAttributeTable.Block.Length;

            this.FieldMarshalTable = new FieldMarshalTableReader(rowCounts[(int)TableIndex.FieldMarshal], IsDeclaredSorted(TableMask.FieldMarshal), hasFieldMarshalRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FieldMarshalTable.Block.Length;

            this.DeclSecurityTable = new DeclSecurityTableReader(rowCounts[(int)TableIndex.DeclSecurity], IsDeclaredSorted(TableMask.DeclSecurity), hasDeclSecurityRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.DeclSecurityTable.Block.Length;

            this.ClassLayoutTable = new ClassLayoutTableReader(rowCounts[(int)TableIndex.ClassLayout], IsDeclaredSorted(TableMask.ClassLayout), referenceSizes[(int)TableIndex.TypeDef], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ClassLayoutTable.Block.Length;

            this.FieldLayoutTable = new FieldLayoutTableReader(rowCounts[(int)TableIndex.FieldLayout], IsDeclaredSorted(TableMask.FieldLayout), referenceSizes[(int)TableIndex.Field], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FieldLayoutTable.Block.Length;

            this.StandAloneSigTable = new StandAloneSigTableReader(rowCounts[(int)TableIndex.StandAloneSig], blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.StandAloneSigTable.Block.Length;

            this.EventMapTable = new EventMapTableReader(rowCounts[(int)TableIndex.EventMap], referenceSizes[(int)TableIndex.TypeDef], eventRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.EventMapTable.Block.Length;

            this.EventPtrTable = new EventPtrTableReader(rowCounts[(int)TableIndex.EventPtr], referenceSizes[(int)TableIndex.Event], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.EventPtrTable.Block.Length;

            this.EventTable = new EventTableReader(rowCounts[(int)TableIndex.Event], typeDefOrRefRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.EventTable.Block.Length;

            this.PropertyMapTable = new PropertyMapTableReader(rowCounts[(int)TableIndex.PropertyMap], referenceSizes[(int)TableIndex.TypeDef], propertyRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.PropertyMapTable.Block.Length;

            this.PropertyPtrTable = new PropertyPtrTableReader(rowCounts[(int)TableIndex.PropertyPtr], referenceSizes[(int)TableIndex.Property], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.PropertyPtrTable.Block.Length;

            this.PropertyTable = new PropertyTableReader(rowCounts[(int)TableIndex.Property], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.PropertyTable.Block.Length;

            this.MethodSemanticsTable = new MethodSemanticsTableReader(rowCounts[(int)TableIndex.MethodSemantics], IsDeclaredSorted(TableMask.MethodSemantics), referenceSizes[(int)TableIndex.MethodDef], hasSemanticsRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodSemanticsTable.Block.Length;

            this.MethodImplTable = new MethodImplTableReader(rowCounts[(int)TableIndex.MethodImpl], IsDeclaredSorted(TableMask.MethodImpl), referenceSizes[(int)TableIndex.TypeDef], methodDefOrRefRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodImplTable.Block.Length;

            this.ModuleRefTable = new ModuleRefTableReader(rowCounts[(int)TableIndex.ModuleRef], stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ModuleRefTable.Block.Length;

            this.TypeSpecTable = new TypeSpecTableReader(rowCounts[(int)TableIndex.TypeSpec], blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.TypeSpecTable.Block.Length;

            this.ImplMapTable = new ImplMapTableReader(rowCounts[(int)TableIndex.ImplMap], IsDeclaredSorted(TableMask.ImplMap), referenceSizes[(int)TableIndex.ModuleRef], memberForwardedRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ImplMapTable.Block.Length;

            this.FieldRvaTable = new FieldRVATableReader(rowCounts[(int)TableIndex.FieldRva], IsDeclaredSorted(TableMask.FieldRva), referenceSizes[(int)TableIndex.Field], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FieldRvaTable.Block.Length;

            this.EncLogTable = new EnCLogTableReader(rowCounts[(int)TableIndex.EncLog], metadataTablesMemoryBlock, totalRequiredSize, this.metadataStreamKind);
            totalRequiredSize += this.EncLogTable.Block.Length;

            this.EncMapTable = new EnCMapTableReader(rowCounts[(int)TableIndex.EncMap], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.EncMapTable.Block.Length;

            this.AssemblyTable = new AssemblyTableReader(rowCounts[(int)TableIndex.Assembly], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.AssemblyTable.Block.Length;

            this.AssemblyProcessorTable = new AssemblyProcessorTableReader(rowCounts[(int)TableIndex.AssemblyProcessor], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.AssemblyProcessorTable.Block.Length;

            this.AssemblyOSTable = new AssemblyOSTableReader(rowCounts[(int)TableIndex.AssemblyOS], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.AssemblyOSTable.Block.Length;

            this.AssemblyRefTable = new AssemblyRefTableReader((int)rowCounts[(int)TableIndex.AssemblyRef], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize, this.metadataKind);
            totalRequiredSize += this.AssemblyRefTable.Block.Length;

            this.AssemblyRefProcessorTable = new AssemblyRefProcessorTableReader(rowCounts[(int)TableIndex.AssemblyRefProcessor], referenceSizes[(int)TableIndex.AssemblyRef], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.AssemblyRefProcessorTable.Block.Length;

            this.AssemblyRefOSTable = new AssemblyRefOSTableReader(rowCounts[(int)TableIndex.AssemblyRefOS], referenceSizes[(int)TableIndex.AssemblyRef], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.AssemblyRefOSTable.Block.Length;

            this.FileTable = new FileTableReader(rowCounts[(int)TableIndex.File], stringHeapRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.FileTable.Block.Length;

            this.ExportedTypeTable = new ExportedTypeTableReader(rowCounts[(int)TableIndex.ExportedType], implementationRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ExportedTypeTable.Block.Length;

            this.ManifestResourceTable = new ManifestResourceTableReader(rowCounts[(int)TableIndex.ManifestResource], implementationRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.ManifestResourceTable.Block.Length;

            this.NestedClassTable = new NestedClassTableReader(rowCounts[(int)TableIndex.NestedClass], IsDeclaredSorted(TableMask.NestedClass), referenceSizes[(int)TableIndex.TypeDef], metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.NestedClassTable.Block.Length;

            this.GenericParamTable = new GenericParamTableReader(rowCounts[(int)TableIndex.GenericParam], IsDeclaredSorted(TableMask.GenericParam), typeOrMethodDefRefSize, stringHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.GenericParamTable.Block.Length;

            this.MethodSpecTable = new MethodSpecTableReader(rowCounts[(int)TableIndex.MethodSpec], methodDefOrRefRefSize, blobHeapRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.MethodSpecTable.Block.Length;

            this.GenericParamConstraintTable = new GenericParamConstraintTableReader(rowCounts[(int)TableIndex.GenericParamConstraint], IsDeclaredSorted(TableMask.GenericParamConstraint), referenceSizes[(int)TableIndex.GenericParam], typeDefOrRefRefSize, metadataTablesMemoryBlock, totalRequiredSize);
            totalRequiredSize += this.GenericParamConstraintTable.Block.Length;

            if (totalRequiredSize > metadataTablesMemoryBlock.Length)
            {
                throw new BadImageFormatException(MetadataResources.MetadataTablesTooSmall);
            }
        }
Пример #30
0
        private unsafe void TestComparisons(string heapValue, int offset, string value, bool unicode = false, bool ignoreCase = false)
        {
            byte[] heap;
            MetadataStringDecoder decoder = MetadataStringDecoder.DefaultUTF8;

            fixed (byte* heapPtr = (heap = Encoding.UTF8.GetBytes(heapValue)))
            {
                var block = new MemoryBlock(heapPtr, heap.Length);
                string heapSubstr = GetStringHeapValue(heapValue, offset);

                // compare:
                if (!unicode)
                {
                    int actualCmp = block.CompareUtf8NullTerminatedStringWithAsciiString(offset, value);
                    int expectedCmp = StringComparer.Ordinal.Compare(heapSubstr, value);
                    Assert.Equal(Math.Sign(expectedCmp), Math.Sign(actualCmp));
                }

                if (!ignoreCase)
                {
                    TestComparison(block, offset, value, heapSubstr, decoder, ignoreCase: true);
                }

                TestComparison(block, offset, value, heapSubstr, decoder, ignoreCase);
            }
        }