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); }
internal StateMachineMethodTableReader( int numberOfRows, bool declaredSorted, int methodRefSize, MemoryBlock containingBlock, int containingBlockOffset) { NumberOfRows = numberOfRows; _isMethodRefSizeSmall = methodRefSize == 2; _kickoffMethodOffset = methodRefSize; RowSize = _kickoffMethodOffset + methodRefSize; Block = containingBlock.GetMemoryBlockAt(containingBlockOffset, RowSize * numberOfRows); if (numberOfRows > 0 && !declaredSorted) { Throw.TableNotSorted(TableIndex.StateMachineMethod); } }
// Trims the alignment padding of the heap. // See StgStringPool::InitOnMem in ndp\clr\src\Utilcode\StgPool.cpp. // This is especially important for EnC. private static MemoryBlock TrimEnd(MemoryBlock block) { if (block.Length == 0) { return(block); } int i = block.Length - 1; while (i >= 0 && block.PeekByte(i) == 0) { i--; } // this shouldn't happen in valid metadata: if (i == block.Length - 1) { return(block); } // +1 for terminating \0 return(block.GetMemoryBlockAt(0, i + 2)); }
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); } }
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"); } }