Remove Mono.Cecil dependency from poison infra (#15311)
This commit is contained in:
commit
2c3a2aeea4
3 changed files with 41 additions and 77 deletions
|
@ -4,7 +4,6 @@
|
|||
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using Mono.Cecil;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
@ -12,6 +11,7 @@ using System.Diagnostics;
|
|||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
|
@ -261,22 +261,10 @@ namespace Microsoft.DotNet.SourceBuild.Tasks.LeakDetection
|
|||
|
||||
try
|
||||
{
|
||||
memStream.Seek(0, SeekOrigin.Begin);
|
||||
using (var asm = AssemblyDefinition.ReadAssembly(memStream))
|
||||
AssemblyName asm = AssemblyName.GetAssemblyName(fileToCheck);
|
||||
if (IsAssemblyPoisoned(fileToCheck))
|
||||
{
|
||||
foreach (var a in asm.CustomAttributes)
|
||||
{
|
||||
foreach (var ca in a.ConstructorArguments)
|
||||
{
|
||||
if (ca.Type.Name == asm.MainModule.TypeSystem.String.Name)
|
||||
{
|
||||
if (ca.Value.ToString().Contains(PoisonMarker))
|
||||
{
|
||||
poisonEntry.Type |= PoisonType.AssemblyAttribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
poisonEntry.Type |= PoisonType.AssemblyAttribute;
|
||||
}
|
||||
}
|
||||
catch
|
||||
|
@ -287,6 +275,27 @@ namespace Microsoft.DotNet.SourceBuild.Tasks.LeakDetection
|
|||
return poisonEntry.Type != PoisonType.None ? poisonEntry : null;
|
||||
}
|
||||
|
||||
private static bool IsAssemblyPoisoned(string path)
|
||||
{
|
||||
byte[] buffer = File.ReadAllBytes(path);
|
||||
byte[] marker = Encoding.UTF8.GetBytes(PoisonMarker);
|
||||
|
||||
// Start at end of file and go backwards
|
||||
// Marker is likely at the end and this saves time when
|
||||
// we encounter a poisoned file.
|
||||
for (int j = buffer.Length - marker.Length; j >= 0; j--)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < marker.Length && buffer[j + i] == marker[i]; i++) ;
|
||||
if (i == marker.Length)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private static PoisonedFileEntry ExtractAndCheckZipFileOnly(IEnumerable<CatalogPackageEntry> catalogedPackages, string zipToCheck, string markerFileName, string tempDir, Queue<string> futureFilesToCheck)
|
||||
{
|
||||
var poisonEntry = new PoisonedFileEntry();
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
|
||||
using Microsoft.Build.Framework;
|
||||
using Microsoft.Build.Utilities;
|
||||
using Mono.Cecil;
|
||||
using Mono.Collections.Generic;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
@ -87,24 +85,23 @@ namespace Microsoft.DotNet.SourceBuild.Tasks.LeakDetection
|
|||
var packageTempPath = Path.Combine(tempDir.FullName, Path.GetFileName(p.ItemSpec));
|
||||
ZipFile.ExtractToDirectory(p.ItemSpec, packageTempPath, true);
|
||||
|
||||
foreach (string f in Directory.EnumerateFiles(packageTempPath, "*", SearchOption.AllDirectories))
|
||||
foreach (string file in Directory.EnumerateFiles(packageTempPath, "*", SearchOption.AllDirectories))
|
||||
{
|
||||
// remove signatures so we don't later fail validation
|
||||
if (Path.GetFileName(f) == ".signature.p7s")
|
||||
if (Path.GetFileName(file) == ".signature.p7s")
|
||||
{
|
||||
File.Delete(f);
|
||||
File.Delete(file);
|
||||
continue;
|
||||
}
|
||||
|
||||
var catalogFileEntry = new CatalogFileEntry();
|
||||
packageEntry.Files.Add(catalogFileEntry);
|
||||
catalogFileEntry.Path = Utility.MakeRelativePath(f, packageTempPath);
|
||||
AssemblyDefinition asm = null;
|
||||
catalogFileEntry.Path = Utility.MakeRelativePath(file, packageTempPath);
|
||||
|
||||
// There seem to be some weird issues with using a file stream both for hashing and
|
||||
// assembly loading, even closing it in between. Use a MemoryStream to avoid issues.
|
||||
var memStream = new MemoryStream();
|
||||
using (var stream = File.OpenRead(f))
|
||||
using (var stream = File.OpenRead(file))
|
||||
{
|
||||
stream.CopyTo(memStream);
|
||||
}
|
||||
|
@ -113,49 +110,23 @@ namespace Microsoft.DotNet.SourceBuild.Tasks.LeakDetection
|
|||
memStream.Seek(0, SeekOrigin.Begin);
|
||||
catalogFileEntry.OriginalHash = sha.ComputeHash(memStream);
|
||||
|
||||
// Now try to read it as an assembly
|
||||
memStream.Seek(0, SeekOrigin.Begin);
|
||||
// Add poison marker to assemblies
|
||||
try
|
||||
{
|
||||
asm = AssemblyDefinition.ReadAssembly(memStream, new ReaderParameters(ReadingMode.Deferred));
|
||||
AssemblyName asm = AssemblyName.GetAssemblyName(file);
|
||||
Poison(file);
|
||||
|
||||
// then get the hash of the now-poisoned file
|
||||
using (var stream = File.OpenRead(file))
|
||||
{
|
||||
catalogFileEntry.PoisonedHash = sha.ComputeHash(stream);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// this is okay, it's not an assembly we can read
|
||||
// this is okay, it's not an assembly
|
||||
}
|
||||
|
||||
// if we read it, now poison and write it back out
|
||||
if (asm != null)
|
||||
{
|
||||
Poison(asm);
|
||||
|
||||
try
|
||||
{
|
||||
// Cecil doesn't try to do some modifications until it writes out the file,
|
||||
// and then throws after we've already truncated the file if it finds out it can't do them.
|
||||
// Write to a memory stream first and then copy to the real stream if it suceeds. If it
|
||||
// fails, we won't truncate the file and we will depend on hashes instead in that case.
|
||||
using (var testMemStream = new MemoryStream())
|
||||
{
|
||||
asm.Write(testMemStream);
|
||||
testMemStream.Seek(0, SeekOrigin.Begin);
|
||||
using (var stream = File.Open(f, FileMode.Create, FileAccess.ReadWrite))
|
||||
{
|
||||
testMemStream.CopyTo(stream);
|
||||
}
|
||||
}
|
||||
|
||||
// then get the hash of the now-poisoned file
|
||||
using (var stream = File.OpenRead(f))
|
||||
{
|
||||
catalogFileEntry.PoisonedHash = sha.ComputeHash(stream);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// see above note in the try - this is okay.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(MarkerFileName))
|
||||
|
@ -203,16 +174,6 @@ namespace Microsoft.DotNet.SourceBuild.Tasks.LeakDetection
|
|||
return !Log.HasLoggedErrors;
|
||||
}
|
||||
|
||||
private void Poison(AssemblyDefinition asm)
|
||||
{
|
||||
foreach (var attr in asm.CustomAttributes)
|
||||
{
|
||||
if (this.AssemblyPropertiesToReplace.Any(p => p.Name == attr.AttributeType.Name))
|
||||
{
|
||||
attr.ConstructorArguments.Clear();
|
||||
attr.ConstructorArguments.Add(new CustomAttributeArgument(asm.MainModule.TypeSystem.String, "POISONED by DotNetSourceBuild - Should not ship"));
|
||||
}
|
||||
}
|
||||
}
|
||||
private void Poison(string path) => File.AppendAllText(path, PoisonMarker);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,12 +13,6 @@
|
|||
<PackageReference Include="Microsoft.Build.Utilities.Core">
|
||||
<Version>15.7.179</Version>
|
||||
</PackageReference>
|
||||
<ProjectReference Include="$(SubmoduleDirectory)linker/external/cecil/Mono.Cecil.csproj">
|
||||
<SetConfiguration Condition=" '$(Configuration)' == 'Debug' ">Configuration=netstandard_Debug</SetConfiguration>
|
||||
<SetConfiguration Condition=" '$(Configuration)' == 'Release' ">Configuration=netstandard_Release</SetConfiguration>
|
||||
<Project>{D68133BD-1E63-496E-9EDE-4FBDBF77B486}</Project>
|
||||
<Name>Mono.Cecil</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="../Microsoft.DotNet.SourceBuild.Tasks.XPlat/Microsoft.DotNet.SourceBuild.Tasks.XPlat.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
|
Loading…
Reference in a new issue