From ed271d2d853764703986d2613499b787271e26f2 Mon Sep 17 00:00:00 2001 From: Cameron Taggart Date: Sun, 26 Mar 2017 14:40:05 -0500 Subject: [PATCH] fix #179 AccessViolation in sourcelink test --- .../dotnet-sourcelink-git.csproj | 1 + dotnet-sourcelink/DebugReaderProvider.cs | 55 +++++++++++++++++++ dotnet-sourcelink/Program.cs | 33 ++--------- dotnet-sourcelink/dotnet-sourcelink.csproj | 1 + 4 files changed, 63 insertions(+), 27 deletions(-) create mode 100644 dotnet-sourcelink/DebugReaderProvider.cs diff --git a/dotnet-sourcelink-git/dotnet-sourcelink-git.csproj b/dotnet-sourcelink-git/dotnet-sourcelink-git.csproj index c7ed8a1..9321165 100644 --- a/dotnet-sourcelink-git/dotnet-sourcelink-git.csproj +++ b/dotnet-sourcelink-git/dotnet-sourcelink-git.csproj @@ -4,6 +4,7 @@ Exe netcoreapp1.0 DotnetCliTool + SourceLink.Git diff --git a/dotnet-sourcelink/DebugReaderProvider.cs b/dotnet-sourcelink/DebugReaderProvider.cs new file mode 100644 index 0000000..8123537 --- /dev/null +++ b/dotnet-sourcelink/DebugReaderProvider.cs @@ -0,0 +1,55 @@ +using System; +using System.IO; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; + +namespace SourceLink +{ + public class DebugReaderProvider : IDisposable + { + private Stream stream; + private MetadataReaderProvider provider; + + public DebugReaderProvider(string path) + { + stream = File.OpenRead(path); + if (path.EndsWith(".dll")) + { + var reader = new PEReader(stream); + if (reader.HasMetadata) + { + // https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs#L392 + var debugDirectoryEntries = reader.ReadDebugDirectory(); + if (debugDirectoryEntries.Length < 3) return; + provider = reader.ReadEmbeddedPortablePdbDebugDirectoryData(debugDirectoryEntries[2]); + } + } + else + { + provider = MetadataReaderProvider.FromPortablePdbStream(stream); + } + } + + public MetadataReader GetMetaDataReader() + { + return provider.GetMetadataReader(); + } + + // Basic Dispose Pattern https://msdn.microsoft.com/en-us/library/b1yfkh5e(v=vs.110).aspx#Anchor_0 + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + protected virtual void Dispose(bool disposing) + { + if (disposing) + { + if (provider != null) provider.Dispose(); + if (stream != null) stream.Dispose(); + } + } + } + + +} diff --git a/dotnet-sourcelink/Program.cs b/dotnet-sourcelink/Program.cs index cdb42b5..374dab8 100644 --- a/dotnet-sourcelink/Program.cs +++ b/dotnet-sourcelink/Program.cs @@ -10,7 +10,6 @@ using System.Net.Http; using System.Net.Http.Headers; using System.Security.Cryptography; -using System.Reflection.PortableExecutable; namespace SourceLink { public class Program @@ -234,33 +233,11 @@ public static void Test(CommandLineApplication command) public static readonly Guid SourceLinkId = new Guid("CC110556-A091-4D38-9FEC-25AB9A351A6A"); - public static MetadataReader GetMetaDataReader(string path, Stream stream) - { - if (path.EndsWith(".dll")) - { - var reader = new PEReader(stream); - if (reader.HasMetadata) - { - // https://github.com/dotnet/corefx/blob/master/src/System.Reflection.Metadata/tests/PortableExecutable/PEReaderTests.cs#L392 - var debugDirectoryEntries = reader.ReadDebugDirectory(); - if (debugDirectoryEntries.Length < 3) return null; - var embeddedProvider = reader.ReadEmbeddedPortablePdbDebugDirectoryData(debugDirectoryEntries[2]); - return embeddedProvider.GetMetadataReader(); - } - } - else - { - var mrp = MetadataReaderProvider.FromPortablePdbStream(stream); - return mrp.GetMetadataReader(); - } - return null; - } - public static byte[] GetSourceLinkBytes(string path) { - using (var file = File.OpenRead(path)) + using (var drp = new DebugReaderProvider(path)) { - var mr = GetMetaDataReader(path, file); + var mr = drp.GetMetaDataReader(); if (mr == null) return null; var blobh = default(BlobHandle); foreach (var cdih in mr.GetCustomDebugInformation(EntityHandle.ModuleDefinition)) @@ -289,12 +266,14 @@ public static bool IsEmbedded(MetadataReader mr, DocumentHandle dh) public static IEnumerable GetDocuments(string path) { - using (var file = File.OpenRead(path)) + using (var drp = new DebugReaderProvider(path)) { - var mr = GetMetaDataReader(path, file); + var mr = drp.GetMetaDataReader(); foreach (var dh in mr.Documents) { + if (dh.IsNil) continue; var d = mr.GetDocument(dh); + if (d.Name.IsNil || d.Language.IsNil || d.HashAlgorithm.IsNil || d.Hash.IsNil) continue; yield return new Document { Name = mr.GetString(d.Name), diff --git a/dotnet-sourcelink/dotnet-sourcelink.csproj b/dotnet-sourcelink/dotnet-sourcelink.csproj index 0b31014..b549e1d 100644 --- a/dotnet-sourcelink/dotnet-sourcelink.csproj +++ b/dotnet-sourcelink/dotnet-sourcelink.csproj @@ -4,6 +4,7 @@ Exe netcoreapp1.0 DotnetCliTool + SourceLink