// internal for testing internal static unsafe ImmutableArray <byte> DecodeEmbeddedPortablePdbDebugDirectoryData(AbstractMemoryBlock block) { byte[] decompressed; const int headerSize = 2 * sizeof(int); var headerReader = new BlobReader(block.Pointer, headerSize); if (headerReader.ReadUInt32() != PortablePdbVersions.DebugDirectoryEmbeddedSignature) { throw new BadImageFormatException(SR.UnexpectedEmbeddedPortablePdbDataSignature); } int decompressedSize = headerReader.ReadInt32(); try { decompressed = new byte[decompressedSize]; } catch { throw new BadImageFormatException(SR.DataTooBig); } var compressed = new ReadOnlyUnmanagedMemoryStream(block.Pointer + headerSize, block.Size - headerSize); var deflate = new DeflateStream(compressed, CompressionMode.Decompress, leaveOpen: true); if (decompressedSize > 0) { int actualLength; try { actualLength = deflate.TryReadAll(decompressed, 0, decompressed.Length); } catch (InvalidDataException e) { throw new BadImageFormatException(e.Message, e.InnerException); } if (actualLength != decompressed.Length) { throw new BadImageFormatException(SR.SizeMismatch); } } // Check that there is no more compressed data left, // in case the decompressed size specified in the header is smaller // than the actual decompressed size of the data. if (deflate.ReadByte() != -1) { throw new BadImageFormatException(SR.SizeMismatch); } return(ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref decompressed)); }
internal static unsafe ImmutableArray <byte> DecodeEmbeddedPortablePdbDebugDirectoryData(AbstractMemoryBlock block) { byte[] decompressed; var headerReader = block.GetReader(); if (headerReader.ReadUInt32() != PortablePdbVersions.DebugDirectoryEmbeddedSignature) { throw new BadImageFormatException("UnexpectedEmbeddedPortablePdbDataSignature"); } int decompressedSize = headerReader.ReadInt32(); try { decompressed = new byte[decompressedSize]; } catch { throw new BadImageFormatException("DataTooBig"); } var compressed = new ReadOnlyUnmanagedMemoryStream(headerReader.CurrentPointer, headerReader.RemainingBytes); var deflate = new DeflateStream(compressed, CompressionMode.Decompress, leaveOpen: true); if (decompressedSize > 0) { int actualLength; try { actualLength = deflate.TryReadAll(decompressed, 0, decompressed.Length); } catch (InvalidDataException e) { throw new BadImageFormatException(e.Message, e.InnerException); } if (actualLength != decompressed.Length) { throw new BadImageFormatException("SizeMismatch"); } } // Check that there is no more compressed data left, // in case the decompressed size specified in the header is smaller // than the actual decompressed size of the data. if (deflate.ReadByte() != -1) { throw new BadImageFormatException("SizeMismatch"); } return(new ImmutableArray <byte>(decompressed)); }
internal static MetadataReaderProvider CreateProviderFromStream(IStream stream) { var interopStream = new ReadOnlyInteropStream(stream); var header = new byte[2 * sizeof(int)]; int bytesRead = interopStream.TryReadAll(header, 0, header.Length); MetadataReaderProvider provider; // detect Embedded Portable PDB signature: if (bytesRead == header.Length && header[0] == 'M' && header[1] == 'P' && header[2] == 'D' && header[3] == 'B') { int size = BitConverter.ToInt32(header, startIndex: sizeof(int)); // TODO: https://github.com/dotnet/symreader-portable/issues/47 // We could avoid allocating managed memory here if FromPortablePdbImage accepted non-seekable stream in prefetch mode. // The implementation in S.R.M. allocates native memory. byte[] decompressed; try { decompressed = new byte[size]; } catch { throw new BadImageFormatException(); } var deflate = new DeflateStream(interopStream, CompressionMode.Decompress, leaveOpen: true); if (size > 0) { int actualLength; try { actualLength = deflate.TryReadAll(decompressed, 0, decompressed.Length); } catch (InvalidDataException e) { throw new BadImageFormatException(e.Message, e.InnerException); } if (actualLength != decompressed.Length) { throw new BadImageFormatException(); } } // Check that there is no more compressed data left, // in case the decompressed size specified in the header is smaller // than the actual decompressed size of the data. if (deflate.ReadByte() != -1) { throw new BadImageFormatException(); } provider = MetadataReaderProvider.FromPortablePdbImage(ImmutableByteArrayInterop.DangerousCreateFromUnderlyingArray(ref decompressed)); } else { interopStream.Position = 0; provider = MetadataReaderProvider.FromPortablePdbStream(interopStream); } return(provider); }
// internal for testing internal static unsafe NativeHeapMemoryBlock DecodeEmbeddedPortablePdbDebugDirectoryData(AbstractMemoryBlock block) { NativeHeapMemoryBlock?decompressed; var headerReader = block.GetReader(); if (headerReader.ReadUInt32() != PortablePdbVersions.DebugDirectoryEmbeddedSignature) { throw new BadImageFormatException(SR.UnexpectedEmbeddedPortablePdbDataSignature); } int decompressedSize = headerReader.ReadInt32(); try { decompressed = new NativeHeapMemoryBlock(decompressedSize); } catch { throw new BadImageFormatException(SR.DataTooBig); } bool success = false; try { var compressed = new ReadOnlyUnmanagedMemoryStream(headerReader.CurrentPointer, headerReader.RemainingBytes); var deflate = new DeflateStream(compressed, CompressionMode.Decompress, leaveOpen: true); if (decompressedSize > 0) { int actualLength; try { #if NETCOREAPP3_0_OR_GREATER actualLength = deflate.TryReadAll(new Span <byte>(decompressed.Pointer, decompressed.Size)); #else using var decompressedStream = new UnmanagedMemoryStream(decompressed.Pointer, decompressed.Size, decompressed.Size, FileAccess.Write); deflate.CopyTo(decompressedStream); actualLength = (int)decompressedStream.Position; #endif } catch (Exception e) { throw new BadImageFormatException(e.Message, e.InnerException); } if (actualLength != decompressed.Size) { throw new BadImageFormatException(SR.SizeMismatch); } } // Check that there is no more compressed data left, // in case the decompressed size specified in the header is smaller // than the actual decompressed size of the data. if (deflate.ReadByte() != -1) { throw new BadImageFormatException(SR.SizeMismatch); } success = true; } finally { if (!success) { decompressed.Dispose(); } } return(decompressed); }