public void Log(ReportingDescriptor rule, Result result) { if (!cacheLoggingData) { return; } switch (result.Level) { // These result types are optionally emitted. case FailureLevel.None: case FailureLevel.Note: { if (Verbose) { CacheResult(rule, result); } break; } // These result types are always emitted. case FailureLevel.Error: case FailureLevel.Warning: { CacheResult(rule, result); break; } default: { throw new InvalidOperationException(); } } }
public void SarifExtensions_Result_GetMessageText_Concise_Truncated() { var result = new Result { Message = new Message { Id = "ruleStr1" } }; var rule = new ReportingDescriptor { MessageStrings = new Dictionary <string, MultiformatMessageString> { ["ruleStr1"] = new MultiformatMessageString { Text = "First sentence is very long. Second sentence." } } }; const string Expected = "First sentence is ve\u2026"; // \u2026 is Unicode "horizontal ellipsis". int maxLength = Expected.Length - 1; // The -1 is for the ellipsis character. string actual = result.GetMessageText(rule, concise: true, maxLength); Assert.Equal(Expected, actual); }
public static string FormatForVisualStudio(this Result result, ReportingDescriptor rule) { if (result == null) { throw new ArgumentNullException(nameof(result)); } if (rule == null) { throw new ArgumentNullException(nameof(rule)); } var messageLines = new List <string>(); foreach (var location in result.Locations) { Uri uri = location.PhysicalLocation.ArtifactLocation.Uri; string path = uri.IsAbsoluteUri && uri.IsFile ? uri.LocalPath : uri.ToString(); messageLines.Add( string.Format( CultureInfo.InvariantCulture, "{0}{1}: {2} {3}: {4}", path, location.PhysicalLocation.Region.FormatForVisualStudio(), result.Level.FormatForVisualStudio(), result.RuleId, result.GetMessageText(rule) )); } return(string.Join(Environment.NewLine, messageLines)); }
public void SarifExtensions_Result_GetMessageText_Concise() { var result = new Result() { Message = new Message() { Arguments = new List <string> { "fox", "dog" }, MessageId = "ruleStr1" } }; var rule = new ReportingDescriptor() { MessageStrings = new Dictionary <string, MultiformatMessageString>() { ["ruleStr1"] = new MultiformatMessageString { Text = "The quick brown {0} jumps over the lazy {1}. That {1} sure is lazy!" } } }; string expected = "The quick brown fox jumps over the lazy dog."; string actual = result.GetMessageText(rule, concise: true); Assert.Equal(expected, actual); }
public virtual ReportingDescriptor VisitReportingDescriptor(ReportingDescriptor node) { if (node != null) { node.Name = VisitNullChecked(node.Name); node.ShortDescription = VisitNullChecked(node.ShortDescription); node.FullDescription = VisitNullChecked(node.FullDescription); if (node.MessageStrings != null) { var keys = node.MessageStrings.Keys.ToArray(); foreach (var key in keys) { var value = node.MessageStrings[key]; if (value != null) { node.MessageStrings[key] = VisitNullChecked(value); } } } node.DefaultConfiguration = VisitNullChecked(node.DefaultConfiguration); node.Help = VisitNullChecked(node.Help); } return(node); }
private void LogSimpleResult(SarifLogger sarifLogger) { ReportingDescriptor rule = new ReportingDescriptor { Id = "RuleId" }; sarifLogger.Log(rule, CreateSimpleResult(rule)); }
private void CacheResult(ReportingDescriptor rule, Result result) { if (!HashToResultsMap.TryGetValue(currentFileHash, out List <Tuple <ReportingDescriptor, Result> > results)) { results = HashToResultsMap[currentFileHash] = new List <Tuple <ReportingDescriptor, Result> >(); } results.Add(new Tuple <ReportingDescriptor, Result>(rule, result)); }
/// <summary> /// Look up the ReportingDescriptor for this Result. /// </summary> /// <param name="run">Run instance containing this Result</param> /// <returns>ReportingDescriptor for Result Rule, if available</returns> public ReportingDescriptor GetRule(Run run = null) { // Follows SARIF Spec 3.52.3 (reportingDescriptor lookup) // Ensure run argument or Result.Run was set if (run == null) { EnsureRunProvided(); run = this.Run; } if (run != null) { // Find the 'ToolComponent' for this Result (Run.Tool.Driver if absent) ToolComponent component = run.GetToolComponentFromReference(this.Rule?.ToolComponent); IList <ReportingDescriptor> rules = component?.Rules; // Look up by this.RuleIndex, if present if (this.RuleIndex >= 0) { return(GetRuleByIndex(rules, this.RuleIndex)); } // Look up by this.Rule.Index, if present if (this.Rule?.Index >= 0) { return(GetRuleByIndex(rules, this.Rule.Index)); } // Look up by this.Rule.Guid, if present if (!string.IsNullOrEmpty(this.Rule?.Guid) && rules != null) { ReportingDescriptor rule = component.GetRuleByGuid(this.Rule.Guid); if (rule != null) { return(rule); } } // Look up by this.RuleId or this.Rule.Id, if present string ruleId = this.RuleId ?? this.Rule?.Id; if (ruleId != null && rules != null) { ReportingDescriptor rule = component.GetRuleById(ruleId); if (rule != null) { return(rule); } } } // Otherwise, metadata is not available and RuleId is the only available property return(new ReportingDescriptor() { Id = this.RuleId ?? this.Rule?.Id }); }
/// <summary> /// Initializes a new instance of the <see cref="ReportingDescriptor" /> class from the specified instance. /// </summary> /// <param name="other"> /// The instance from which the new instance is to be initialized. /// </param> /// <exception cref="ArgumentNullException"> /// Thrown if <paramref name="other" /> is null. /// </exception> public ReportingDescriptor(ReportingDescriptor other) { if (other == null) { throw new ArgumentNullException(nameof(other)); } Init(other.Id, other.Guid, other.Name, other.DeprecatedIds, other.ShortDescription, other.FullDescription, other.MessageStrings, other.DefaultConfiguration, other.HelpUri, other.Help, other.TaxonomyReferences, other.OptionalTaxonomyReferences, other.Properties); }
private Result CreateSimpleResult(ReportingDescriptor rule) { return(new Result { RuleId = rule.Id, Message = new Message { Text = "Some testing occurred." } }); }
public ReportingDescriptor GetRuleByGuid(string ruleGuid) { ReportingDescriptor rule = null; // Build lookup if not built or possibly out-of-date if (_cachedRulesByGuid?.TryGetValue(ruleGuid, out rule) != true) { BuildRuleCaches(); _cachedRulesByGuid.TryGetValue(ruleGuid, out rule); } return(rule); }
public ReportingDescriptor GetRuleById(string ruleId) { ReportingDescriptor rule = null; // Build lookup if not built or possibly out-of-date if (_cachedRulesById == null || !_cachedRulesById.TryGetValue(ruleId, out rule)) { BuildRuleCaches(); _cachedRulesById.TryGetValue(ruleId, out rule); } return(rule); }
public static string GetMessageText(this Result result, ReportingDescriptor rule, bool concise = false) { if (result == null) { throw new ArgumentNullException(nameof(result)); } string text = result.Message?.Text; if (string.IsNullOrEmpty(text)) { text = string.Empty; // Ensure that it's not null. if (rule != null) { string messageId = result.Message?.MessageId; MultiformatMessageString formatString = null; if (!string.IsNullOrWhiteSpace(messageId) && rule.MessageStrings?.TryGetValue(messageId, out formatString) == true) { string[] arguments = null; if (result.Message?.Arguments != null) { arguments = new string[result.Message.Arguments.Count]; result.Message.Arguments.CopyTo(arguments, 0); } else { arguments = new string[0]; } text = GetFormattedMessage(formatString.Text, arguments); } } } if (concise) { text = GetFirstSentence(text); } return(text); }
public void SarifLogger_AcceptsSubrulesInResultRuleId() { var sb = new StringBuilder(); using (var textWriter = new StringWriter(sb)) { using (var sarifLogger = new SarifLogger(textWriter)) { var rule = new ReportingDescriptor { Id = "RuleId" }; var result = new Result { RuleId = "RuleId/1" }; Action action = () => sarifLogger.Log(rule, result); action.Should().NotThrow(); } } }
public void Log(ReportingDescriptor rule, Result result) { if (result == null) { throw new ArgumentNullException(nameof(result)); } string message = result.GetMessageText(rule); // TODO we need better retrieval for locations than these defaults // Note that we can potentially emit many messages from a single result PhysicalLocation physicalLocation = result.Locations?.First().PhysicalLocation; WriteToConsole( result.Kind, result.Level, physicalLocation?.ArtifactLocation?.Uri, physicalLocation?.Region, result.RuleId, message); }
public virtual ReportingDescriptor VisitReportingDescriptor(ReportingDescriptor node) { if (node != null) { node.ShortDescription = VisitNullChecked(node.ShortDescription); node.FullDescription = VisitNullChecked(node.FullDescription); if (node.MessageStrings != null) { var keys = node.MessageStrings.Keys.ToArray(); foreach (var key in keys) { var value = node.MessageStrings[key]; if (value != null) { node.MessageStrings[key] = VisitNullChecked(value); } } } node.DefaultConfiguration = VisitNullChecked(node.DefaultConfiguration); node.Help = VisitNullChecked(node.Help); if (node.TaxonomyReferences != null) { for (int index_0 = 0; index_0 < node.TaxonomyReferences.Count; ++index_0) { node.TaxonomyReferences[index_0] = VisitNullChecked(node.TaxonomyReferences[index_0]); } } if (node.OptionalTaxonomyReferences != null) { for (int index_0 = 0; index_0 < node.OptionalTaxonomyReferences.Count; ++index_0) { node.OptionalTaxonomyReferences[index_0] = VisitNullChecked(node.OptionalTaxonomyReferences[index_0]); } } } return(node); }
public void SarifLogger_ResultAndRuleIdMismatch() { var sb = new StringBuilder(); using (var writer = new StringWriter(sb)) using (var sarifLogger = new SarifLogger(writer, LoggingOptions.Verbose)) { var rule = new ReportingDescriptor { Id = "ActualId" }; var result = new Result { RuleId = "IncorrectRuleId", Message = new Message { Text = "test message" } }; Assert.Throws <ArgumentException>(() => sarifLogger.Log(rule, result)); } }
public static string GetMessageText(this Result result, ReportingDescriptor rule) { return(GetMessageText(result, rule, concise: false)); }
public bool ValueEquals(ReportingDescriptor other) => ValueComparer.Equals(this, other);
public void Log(ReportingDescriptor rule, Result result) { NoteTestResult(result.Kind, result.Locations.First().PhysicalLocation.ArtifactLocation.Uri.LocalPath); }
public void SarifLogger_DoNotScrapeFilesFromNotifications() { var sb = new StringBuilder(); using (var textWriter = new StringWriter(sb)) { using (var sarifLogger = new SarifLogger( textWriter, analysisTargets: null, dataToInsert: OptionallyEmittedData.Hashes, invocationTokensToRedact: null, invocationPropertiesToLog: null)) { var toolNotification = new Notification { Locations = new List <Location> { new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri(@"file:///file.cpp") } } } }, Message = new Message { Text = "A notification was raised." } }; sarifLogger.LogToolNotification(toolNotification); var configurationNotification = new Notification { Locations = new List <Location> { new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri(@"file:///file.cpp") } } } }, Message = new Message { Text = "A notification was raised." } }; sarifLogger.LogConfigurationNotification(configurationNotification); string ruleId = "RuleId"; var rule = new ReportingDescriptor { Id = ruleId }; var result = new Result { RuleId = ruleId, Message = new Message { Text = "Some testing occurred." } }; sarifLogger.Log(rule, result); } } string logText = sb.ToString(); var sarifLog = JsonConvert.DeserializeObject <SarifLog>(logText); sarifLog.Runs[0].Artifacts.Should().BeNull(); }
public void SarifLogger_ScrapesFilesFromResult() { var sb = new StringBuilder(); using (var textWriter = new StringWriter(sb)) { using (var sarifLogger = new SarifLogger( textWriter, analysisTargets: null, dataToInsert: OptionallyEmittedData.Hashes, invocationTokensToRedact: null, invocationPropertiesToLog: null)) { string ruleId = "RuleId"; var rule = new ReportingDescriptor { Id = ruleId }; var result = new Result { RuleId = ruleId, Message = new Message { Text = "Some testing occurred." }, AnalysisTarget = new ArtifactLocation { Uri = new Uri(@"file:///file0.cpp") }, Locations = new[] { new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri(@"file:///file1.cpp") } } }, }, Fixes = new[] { new Fix { ArtifactChanges = new[] { new ArtifactChange { ArtifactLocation = new ArtifactLocation { Uri = new Uri(@"file:///file2.cpp") }, Replacements = new[] { new Replacement { DeletedRegion = new Region { StartLine = 1 } } } } }, } }, RelatedLocations = new[] { new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri(@"file:///file3.cpp") } } } }, Stacks = new[] { new Stack { Frames = new[] { new StackFrame { Location = new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri(@"file:///file4.cpp") } } } } } } }, CodeFlows = new[] { new CodeFlow { ThreadFlows = new[] { new ThreadFlow { Locations = new[] { new ThreadFlowLocation { Location = new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri(@"file:///file5.cpp") } } } } } } } } } }; sarifLogger.Log(rule, result); } } string logText = sb.ToString(); var sarifLog = JsonConvert.DeserializeObject <SarifLog>(logText); int fileCount = 6; for (int i = 0; i < fileCount; ++i) { string fileName = @"file" + i + ".cpp"; string fileDataKey = "file:///" + fileName; sarifLog.Runs[0].Artifacts.Where(f => f.Location.Uri.AbsoluteUri.ToString().Contains(fileDataKey)).Any().Should().BeTrue(); } sarifLog.Runs[0].Artifacts.Count.Should().Be(fileCount); }
public override ReportingDescriptor VisitReportingDescriptor(ReportingDescriptor node) { node.DeprecatedGuids[0] = "36D2C336-7730-425A-9A94-43593A2A651C"; return(base.VisitReportingDescriptor(node)); }
public void SarifLogger_WritesFileContentsForAnalysisTargets() { var sb = new StringBuilder(); // Create a temporary file whose extension signals that it is textual. // This ensures that the ArtifactContents.Text property, rather than // the Binary property, is populated, so the test of the Text property // at the end will work. using (var tempFile = new TempFile(".txt")) { string tempFilePath = tempFile.Name; string tempFileDirectory = Path.GetDirectoryName(tempFilePath); string tempFileName = Path.GetFileName(tempFilePath); File.WriteAllText(tempFilePath, "#include \"windows.h\";"); var run = new Run { OriginalUriBaseIds = new Dictionary <string, ArtifactLocation> { [TempFileBaseId] = new ArtifactLocation { Uri = new Uri(tempFileDirectory, UriKind.Absolute) } }, // To get text contents, we also need to specify an encoding that // Encoding.GetEncoding() will accept. DefaultEncoding = "UTF-8" }; var rule = new ReportingDescriptor { Id = TestData.TestRuleId }; // Create a result that refers to an artifact whose location is specified // by a relative reference together with a uriBaseId. var result = new Result { RuleId = rule.Id, Message = new Message { Text = "Testing." }, Locations = new List <Location> { new Location { PhysicalLocation = new PhysicalLocation { ArtifactLocation = new ArtifactLocation { Uri = new Uri(tempFileName, UriKind.Relative), UriBaseId = TempFileBaseId } } } } }; using (var textWriter = new StringWriter(sb)) { // Create a logger that inserts artifact contents. using (var sarifLogger = new SarifLogger( textWriter, run: run, dataToInsert: OptionallyEmittedData.TextFiles)) { sarifLogger.Log(rule, result); } // The logger should have populated the artifact contents. string logText = sb.ToString(); SarifLog sarifLog = JsonConvert.DeserializeObject <SarifLog>(logText); sarifLog.Runs[0].Artifacts[0].Contents?.Text.Should().NotBeNullOrEmpty(); } } }