public static RuleModel ToRuleModel(this ReportingDescriptor rule, string defaultRuleId) { RuleModel model; if (rule == null) { model = new RuleModel() { Id = defaultRuleId, DefaultFailureLevel = FailureLevel.Warning }; } else { model = new RuleModel() { Id = rule.Id, Name = rule.Name, Description = rule.FullDescription?.Text, DefaultFailureLevel = rule.DefaultConfiguration != null ? rule.DefaultConfiguration.Level : FailureLevel.Warning, // Default level HelpUri = rule.HelpUri?.IsAbsoluteUri == true ? rule.HelpUri.AbsoluteUri : null }; } return(model); }
public void Log(ReportingDescriptor rule, Result result) { foreach (IAnalysisLogger logger in Loggers) { logger.Log(rule, result); } }
public void RuleModel_DescriptionWithHyperlink_ShouldHaveInlines() { string descriptionText = "Rule description text with [hyperlink](https://example.com)."; ReportingDescriptor rule = new ReportingDescriptor { Id = testRuleId, Name = testRuleName, DefaultConfiguration = new ReportingConfiguration { Level = FailureLevel.Error, }, FullDescription = new MultiformatMessageString { Text = descriptionText } }; RuleModel ruleModel = rule.ToRuleModel(testRuleId); ruleModel.Description.Should().BeEquivalentTo(descriptionText); ruleModel.DescriptionInlines.Should().NotBeNull(); ruleModel.DescriptionInlines.Count.Should().Be(3); ruleModel.DescriptionInlines[1].GetType().Should().Be(typeof(Hyperlink)); ruleModel.ShowPlainDescription.Should().BeFalse(); }
internal static FailureLevel GetFailureLevelFromRuleMetadata(ReportingDescriptor rule) { // High impact - ["5.0", "3.0") OR any value higher than 5.0 (technically invalid, but we forgive!) => Error // Medium impact - ["3.0", "1.0") => Warning // Low impact - ["1.0", "0,0"] => Note // Negative value or no value => Warning (i.e. treated as no value provided, SARIF defaults this to "Warning"). if (rule.TryGetProperty("Impact", out string impactValue)) { if (float.TryParse(impactValue, out float impact)) { if (impact > 3.0) { return(FailureLevel.Error); } if (impact > 1.0) { return(FailureLevel.Warning); } if (impact >= 0.0) { return(FailureLevel.Note); } } } return(FailureLevel.Warning); // Default value for Result.Level. }
public void Log(ReportingDescriptor rule, Result result) { if (rule == null) { throw new ArgumentNullException(nameof(rule)); } if (result == null) { throw new ArgumentNullException(nameof(result)); } if (rule.GetType().Name != nameof(ReportingDescriptor)) { rule = rule.DeepClone(); } if (rule.Id != result.RuleId) { throw new ArgumentException($"rule.Id is not equal to result.RuleId ({rule.Id} != {result.RuleId})"); } Results ??= new Dictionary <ReportingDescriptor, IList <Result> >(); if (!Results.TryGetValue(rule, out IList <Result> results)) { results = Results[rule] = new List <Result>(); } results.Add(result); }
private void AssertShouldNotSerializeShortDescription(ReportingDescriptor reportingDescriptor, bool should = false) { Assert.False(should ^ reportingDescriptor.ShouldSerializeShortDescription()); string testSerializedString = JsonConvert.SerializeObject(reportingDescriptor); Assert.False(should ^ testSerializedString.Contains(ShortDescription, StringComparison.InvariantCultureIgnoreCase)); }
public void CachingLogger_EmitResultsCorrectlyBasedOnRules() { Result result01 = GenerateResult(); ReportingDescriptor rule01 = GenerateRule(); var logger = new CachingLogger(); Assert.Throws <ArgumentNullException>(() => logger.Log(null, result01)); Assert.Throws <ArgumentNullException>(() => logger.Log(rule01, null)); rule01.Id = "TEST0001"; result01.RuleId = "TEST0002"; Assert.Throws <ArgumentException>(() => logger.Log(rule01, result01)); rule01.Id = "TEST0001"; result01.RuleId = "TEST0001"; // Validate simple insert logger.Log(rule01, result01); logger.Results.Should().HaveCount(1); logger.Results.Should().ContainKey(rule01); // Updating value from a specific key logger.Log(rule01, result01); logger.Results.Should().HaveCount(1); logger.Results.Should().ContainKey(rule01); logger.Results[rule01].Should().HaveCount(2); }
public void Log(ReportingDescriptor rule, Result result) { if (rule == null) { throw new ArgumentNullException(nameof(rule)); } if (result == null) { throw new ArgumentNullException(nameof(result)); } if (!result.RuleId.IsEqualToOrHierarchicalDescendantOf(rule.Id)) { //The rule id '{0}' specified by the result does not match the actual id of the rule '{1}' string message = string.Format(CultureInfo.InvariantCulture, SdkResources.ResultRuleIdDoesNotMatchRule, result.RuleId, rule.Id); throw new ArgumentException(message); } if (!ShouldLog(result.Level)) { return; } result.RuleIndex = LogRule(rule); CaptureFilesInResult(result); _issueLogJsonWriter.WriteResult(result); }
private void AddMessagesToResults() { foreach (Result result in _results) { int ruleIndex = _ruleIdToIndexMap[result.RuleId]; result.RuleIndex = ruleIndex; ReportingDescriptor rule = _rules[ruleIndex]; Message message = new Message(); if (_resultToReplacementDefinitionDictionary.TryGetValue(result, out Dictionary <string, string> replacements)) { string messageText = (rule.ShortDescription ?? rule.FullDescription)?.Text; foreach (string key in replacements.Keys) { string value = replacements[key]; if (SupportedReplacementTokens.Contains(key)) { // Replace the token with an embedded hyperlink messageText = messageText.Replace(string.Format(ReplacementTokenFormat, key), string.Format(EmbeddedLinkFormat, value)); } else { // Replace the token with plain text messageText = messageText.Replace(string.Format(ReplacementTokenFormat, key), value); } } message.Text = messageText; } result.Message = message; } }
private void AnalyzeIdOnlyRules(Run run, string runPointer) { // We only verify first item in the rules array, // since tools will typically generate similar nodes. // This approach may cause occasional false negatives. // Also, `tool` and `driver` are mandatory fields, hence // null check is not required. ReportingDescriptor firstRule = run.Tool.Driver.Rules?.FirstOrDefault(); if (firstRule == null) { return; } string rulesPointer = runPointer .AtProperty(SarifPropertyName.Tool) .AtProperty(SarifPropertyName.Driver) .AtProperty(SarifPropertyName.Rules); string firstRulePointer = rulesPointer.AtIndex(0); if (HasIdOnlyRules(firstRulePointer)) { // The 'rules' array at '{0}' contains no information beyond the ids of the rules. // Removing this array might reduce the log file size without losing information. // In some scenarios (for example, when assessing compliance with policy), the // 'rules' array might be used to record the full set of rules that were evaluated. // In such a scenario, the 'rules' array should be retained even if it contains // only id information. LogResult( rulesPointer, nameof(RuleResources.SARIF2004_OptimizeFileSize_Warning_EliminateIdOnlyRules_Text)); } }
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(); } } }
internal static RuleVersionOne CreateRuleVersionOne(ReportingDescriptor v2ReportingDescriptor) { RuleVersionOne rule = null; if (v2ReportingDescriptor != null) { rule = new RuleVersionOne { FullDescription = v2ReportingDescriptor.FullDescription?.Text, HelpUri = v2ReportingDescriptor.HelpUri, Id = v2ReportingDescriptor.Id, MessageFormats = ConvertToV1MessageStringsDictionary(v2ReportingDescriptor.MessageStrings), Name = v2ReportingDescriptor.Name, Properties = v2ReportingDescriptor.Properties, ShortDescription = v2ReportingDescriptor.ShortDescription?.Text }; if (v2ReportingDescriptor.DefaultConfiguration != null) { rule.Configuration = v2ReportingDescriptor.DefaultConfiguration.Enabled ? RuleConfigurationVersionOne.Enabled : RuleConfigurationVersionOne.Disabled; rule.DefaultLevel = Utilities.CreateResultLevelVersionOne(v2ReportingDescriptor.DefaultConfiguration.Level); } } return(rule); }
protected override void Analyze(ReportingDescriptor reportingDescriptor, string reportingDescriptorPointer) { if (string.IsNullOrWhiteSpace(reportingDescriptor.Name)) { // {0}: The rule '{1}' does not provide a "friendly name" in its 'name' // property. The friendly name should be a single Pascal identifier, for // example, 'ProvideRuleFriendlyName', that helps users see at a glance // the purpose of the rule. LogResult( reportingDescriptorPointer, nameof(RuleResources.SARIF2012_ProvideRuleProperties_Note_ProvideFriendlyName_Text), reportingDescriptor.Id); return; } if (!s_pascalCaseRegex.IsMatch(reportingDescriptor.Name)) { // {0}: '{1}' is not a Pascal identifier. For uniformity of experience across all tools that // produce SARIF, the friendly name should be a single Pascal identifier, for example, // 'ProvideRuleFriendlyName'. LogResult( reportingDescriptorPointer.AtProperty(SarifPropertyName.Name), nameof(RuleResources.SARIF2012_ProvideRuleProperties_Note_FriendlyNameNotAPascalIdentifier_Text), reportingDescriptor.Name); return; } }
private void AddMessagesToResult(Result result) { ReportingDescriptor rule = _rules[result.RuleIndex]; Message message = new Message(); string messageText = (rule.ShortDescription ?? rule.FullDescription)?.Text; if (_currentResultReplacementDictionary != null) { foreach (string key in _currentResultReplacementDictionary.Keys) { string value = _currentResultReplacementDictionary[key]; if (SupportedReplacementTokens.Contains(key)) { // Replace the token with an embedded hyperlink. messageText = messageText.Replace(string.Format(ReplacementTokenFormat, key), string.Format(EmbeddedLinkFormat, value)); } else { // Replace the token with plain text. messageText = messageText.Replace(string.Format(ReplacementTokenFormat, key), value); } } } message.Text = messageText; result.Message = message; }
private static string InjectArguments( string templateText, string organization, string projectName, string pipelineId, string buildDefinitionName, string ruleName, Run run) { // Inject the rule name associated with the defect templateText = templateText.Replace(SCAN_RULE_NAME_PLACEHOLDER, ruleName); // Retrieve the rule descriptor List <ReportingDescriptor> rules = run.Tool.Driver.Rules as List <ReportingDescriptor>; ReportingDescriptor reportingDescriptor = rules.Where(r => r.Id == run.Results[0].GetRule(run).Id).FirstOrDefault(); string exampleText = run.Results[0].GetMessageText(reportingDescriptor); exampleText = NormalizeExampleText(exampleText); templateText = templateText.Replace(SCAN_EXAMPLE_PLACEHOLDER, exampleText); // Inject text from the first result Result sampleResult = run.Results[0]; string anchorLink = GetLinkText(sampleResult.Message.Text); templateText = templateText.Replace(SCAN_TARGET_LINK, BuildAnchorElement(anchorLink, buildDefinitionName)); string jsonPath = GetVariableName(sampleResult.Message.Text); string locationsText = BuildLocationsText(run); templateText = templateText.Replace(SCAN_LOCATIONS, locationsText); return(templateText); }
public override Message VisitMessage(Message node) { if ((node.Text == null || _dataToInsert.HasFlag(OptionallyEmittedData.OverwriteExistingData)) && _dataToInsert.HasFlag(OptionallyEmittedData.FlattenedMessages)) { MultiformatMessageString formatString = null; ReportingDescriptor rule = _ruleIndex != -1 ? _run.Tool.Driver.Rules[_ruleIndex] : null; if (rule != null && rule.MessageStrings != null && rule.MessageStrings.TryGetValue(node.Id, out formatString)) { node.Text = node.Arguments?.Count > 0 ? rule.Format(node.Id, node.Arguments) : formatString?.Text; } if (node.Text == null && _run.Tool.Driver.GlobalMessageStrings?.TryGetValue(node.Id, out formatString) == true) { node.Text = node.Arguments?.Count > 0 ? string.Format(CultureInfo.CurrentCulture, formatString.Text, node.Arguments.ToArray()) : formatString?.Text; } } return(base.VisitMessage(node)); }
public override Result VisitResult(Result node) { // We suspend the visit if there's insufficient data to perform any work if (CurrentRun == null) { throw new InvalidOperationException($"RemapIndicesVisitor requires CurrentRun to be set before Visiting Results."); } // Cache RuleId and set Result.RuleIndex to the (new) index string ruleId = node.ResolvedRuleId(CurrentRun); if (!string.IsNullOrEmpty(ruleId)) { if (RuleIdToIndex.TryGetValue(ruleId, out int ruleIndex)) { node.RuleIndex = ruleIndex; } else { ReportingDescriptor rule = node.GetRule(CurrentRun); int newIndex = Rules.Count; Rules.Add(rule); RuleIdToIndex[ruleId] = newIndex; node.RuleIndex = newIndex; } node.RuleId = ruleId; } Result result = base.VisitResult(node); Results.Add(result); return(result); }
public static RuleModel ToRuleModel(this ReportingDescriptor rule, string defaultRuleId) { RuleModel model; string ruleId = defaultRuleId; if (Guid.TryParse(ruleId, out Guid result) && !(string.IsNullOrEmpty(rule.Name))) { ruleId = rule.Name; } if (rule == null) { model = new RuleModel() { Id = ruleId, DefaultFailureLevel = FailureLevel.Warning }; } else { model = new RuleModel() { Id = ruleId, Name = rule.Name, Description = rule.FullDescription?.Text, DefaultFailureLevel = rule.DefaultConfiguration != null ? rule.DefaultConfiguration.Level : FailureLevel.Warning, // Default level HelpUri = rule.HelpUri?.IsAbsoluteUri == true ? rule.HelpUri.AbsoluteUri : null }; } return(model); }
internal void BuildRule(ReportingDescriptor rule, StringBuilder sb) { sb.Append("## Rule `").Append(rule.Moniker).Append('`').AppendLine(Environment.NewLine); sb.Append("### Description").AppendLine(Environment.NewLine); sb.Append(rule.FullDescription?.Markdown ?? rule.FullDescription?.Text ?? rule.ShortDescription?.Markdown ?? rule.ShortDescription?.Text ?? DriverResources.NoRuleDescription).AppendLine(Environment.NewLine); sb.Append("### Messages").AppendLine(Environment.NewLine); foreach (KeyValuePair <string, MultiformatMessageString> message in rule.MessageStrings) { string ruleName = message.Key; string ruleLevel; Match match = s_friendlyNameRegex.Match(message.Key); if (match.Success) { ruleName = match.Groups["friendlyName"].Value; ruleLevel = match.Groups["level"].Value; } else { ruleLevel = GetLevelFromRuleName(ruleName); } sb.Append("#### `").Append(ruleName).Append("`: ").Append(ruleLevel).AppendLine(Environment.NewLine); sb.Append(message.Value.Markdown ?? message.Value.Text).AppendLine(Environment.NewLine); } sb.Append("---").AppendLine(Environment.NewLine); }
public void FortifyFprConverter_GetFailureLevelFromRuleMetadata_ReturnsAppropriateFailureLevel() { var expectedInputOutputs = new Dictionary <string, FailureLevel> { { "0.0", FailureLevel.Note }, { "0.5", FailureLevel.Note }, { "1.0", FailureLevel.Note }, { "1.1", FailureLevel.Warning }, { "2.0", FailureLevel.Warning }, { "2.5", FailureLevel.Warning }, { "2.9", FailureLevel.Warning }, { "3.0", FailureLevel.Warning }, { "3.1", FailureLevel.Error }, { "3.5", FailureLevel.Error }, { "3.9", FailureLevel.Error }, { "4.5", FailureLevel.Error }, { "5.0", FailureLevel.Error }, { "-5.5", FailureLevel.Warning }, //Invalid value, we default it to Warning { "5.5", FailureLevel.Error }, // Invalid value, we guess that it should be treated as Error }; foreach (KeyValuePair <string, FailureLevel> keyValuePair in expectedInputOutputs) { ReportingDescriptor rule = new ReportingDescriptor(); rule.SetProperty <string>("Impact", keyValuePair.Key); FailureLevel level = FortifyFprConverter.GetFailureLevelFromRuleMetadata(rule); level.Should().Be(keyValuePair.Value); } }
internal ReportingDescriptor CreateRule(RuleVersionOne v1Rule) { ReportingDescriptor rule = null; if (v1Rule != null) { rule = new ReportingDescriptor { FullDescription = CreateMultiformatMessageString(v1Rule.FullDescription), HelpUri = v1Rule.HelpUri, Id = v1Rule.Id, MessageStrings = v1Rule.MessageFormats.ConvertToMultiformatMessageStringsDictionary(), Name = v1Rule.Name, Properties = v1Rule.Properties, ShortDescription = CreateMultiformatMessageString(v1Rule.ShortDescription) }; FailureLevel level = Utilities.CreateReportingConfigurationDefaultLevel(v1Rule.DefaultLevel); rule.DefaultConfiguration = new ReportingConfiguration { Level = level, Enabled = v1Rule.Configuration != RuleConfigurationVersionOne.Disabled }; } return(rule); }
public void FortifyFprConverter_GetFailureLevelFromRuleMetadata_MissingImpactProperty_ReturnsWarning() { ReportingDescriptor rule = new ReportingDescriptor(); FailureLevel level = FortifyFprConverter.GetFailureLevelFromRuleMetadata(rule); level.Should().Be(FailureLevel.Warning); }
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)); }
private static void ReportResult( Result result, IAnalysisLogger logger) { ReportingDescriptor rule = RuleFactory.GetRuleFromRuleId(result.RuleId); logger.Log(rule, result); }
private static void ReportResult(Result result, SarifLogger logger) { ReportingDescriptor rule = RuleFactory.GetRuleFromRuleId(result.RuleId); Console.Error.WriteLine( result.FormatForVisualStudio(rule)); logger.Log(rule, result); }
private static void ReportResult( Result result, IAnalysisLogger logger) { #if JSCHEMA_UPGRADED ReportingDescriptor rule = RuleFactory.GetRuleFromRuleId(result.RuleId); logger.Log(rule, result); #endif }
private static string ConstructFullRuleIdentifier(ReportingDescriptor reportingDescriptor) { string fullRuleIdentifier = reportingDescriptor.Id; if (!string.IsNullOrEmpty(reportingDescriptor.Name)) { fullRuleIdentifier += ": " + reportingDescriptor.Name; } return(fullRuleIdentifier); }
public static PerLanguageOption <T> CreateRuleSpecificOption <T>(ReportingDescriptor rule, PerLanguageOption <T> option) { // This helper returns a copy of a rule option that is qualified by a new feature name constructed // from an arbitrary rule instance. This allows users to create a generic property descriptor // that is further qualified (by feature name) to be associated with a different check. return(new PerLanguageOption <T>( feature: rule.Id + "." + rule.Name, name: option.Name, defaultValue: option.DefaultValue, description: option.Description)); }
private void AnalyzeReportingDescriptor(ReportingDescriptor rule, string reportingDescriptorPointer) { if (rule.MessageStrings != null) { string messageStringsPointer = reportingDescriptorPointer.AtProperty(SarifPropertyName.MessageStrings); foreach (KeyValuePair <string, MultiformatMessageString> message in rule.MessageStrings) { AnalyzeMessageString(rule.Id, message.Value.Text, message.Key, messageStringsPointer.AtProperty(message.Key)); } } }
private int LogRule(ReportingDescriptor rule) { if (!RuleToIndexMap.TryGetValue(rule, out int ruleIndex)) { ruleIndex = RuleToIndexMap.Count; RuleToIndexMap[rule] = ruleIndex; _run.Tool.Driver.Rules = _run.Tool.Driver.Rules ?? new OrderSensitiveValueComparisonList <ReportingDescriptor>(ReportingDescriptor.ValueComparer); _run.Tool.Driver.Rules.Add(rule); } return(ruleIndex); }