diff --git a/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.LeakDetection/CheckForPoison.cs b/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.LeakDetection/CheckForPoison.cs index bccab450d58d..cf16890ced4e 100644 --- a/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.LeakDetection/CheckForPoison.cs +++ b/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.LeakDetection/CheckForPoison.cs @@ -12,8 +12,11 @@ using System.IO.Compression; using System.Linq; using System.Reflection; +using System.Reflection.Metadata; +using System.Reflection.PortableExecutable; using System.Security.Cryptography; using System.Text; +using System.Text.RegularExpressions; using System.Xml; using System.Xml.Linq; @@ -147,6 +150,10 @@ public class CheckForPoison : Task private const string PoisonMarker = "POISONED"; + private const string SbrpAttributeType = "System.Reflection.AssemblyMetadataAttribute"; + + private const string SbrpAttributeValuePattern = "source\\s?source\\-build\\-reference\\-packages"; + private record CandidateFileEntry(string ExtractedPath, string DisplayPath); public override bool Execute() @@ -298,7 +305,11 @@ private static PoisonedFileEntry CheckSingleFile(IEnumerable reader.GetCustomAttribute(attrHandle)) + .Any(attr => IsAttributeSbrp(reader, attr)); + } + + private static bool IsAttributeSbrp(MetadataReader reader, CustomAttribute attr) + { + string attributeType = string.Empty; + + if (attr.Constructor.Kind == HandleKind.MemberReference) + { + MemberReference mref = reader.GetMemberReference((MemberReferenceHandle)attr.Constructor); + + if (mref.Parent.Kind == HandleKind.TypeReference) + { + TypeReference tref = reader.GetTypeReference((TypeReferenceHandle)mref.Parent); + attributeType = $"{reader.GetString(tref.Namespace)}.{reader.GetString(tref.Name)}"; + } + } + + if (attributeType == SbrpAttributeType) + { + BlobReader blobReader = reader.GetBlobReader(attr.Value); + string attributeValue = Encoding.UTF8.GetString(blobReader.ReadBytes(blobReader.Length)); + attributeValue = Regex.Replace(attributeValue, @"\p{C}+", string.Empty); + return Regex.IsMatch(attributeValue, SbrpAttributeValuePattern); + } + return false; + } + private static PoisonedFileEntry ExtractAndCheckZipFileOnly(IEnumerable catalogedPackages, CandidateFileEntry candidate, string markerFileName, string tempDir, Queue futureFilesToCheck) { var poisonEntry = new PoisonedFileEntry(); diff --git a/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.LeakDetection/PoisonType.cs b/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.LeakDetection/PoisonType.cs index de5c35961bda..4ac37e1cb2b0 100644 --- a/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.LeakDetection/PoisonType.cs +++ b/src/SourceBuild/content/eng/tools/tasks/Microsoft.DotNet.SourceBuild.Tasks.LeakDetection/PoisonType.cs @@ -11,5 +11,6 @@ internal enum PoisonType Hash = 1, AssemblyAttribute = 2, NupkgFile = 4, + SourceBuildReferenceAssembly = 8, } } diff --git a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/PoisonUsage.txt b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/PoisonUsage.txt index f1ab9ecc1393..fee5ec5e8b61 100644 --- a/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/PoisonUsage.txt +++ b/src/SourceBuild/content/test/Microsoft.DotNet.SourceBuild.SmokeTests/assets/baselines/PoisonUsage.txt @@ -1 +1,14 @@ - \ No newline at end of file + + + SourceBuildReferenceAssembly + + + SourceBuildReferenceAssembly + + + SourceBuildReferenceAssembly + + + SourceBuildReferenceAssembly + + \ No newline at end of file