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);
     }
 }
Ejemplo n.º 3
0
        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();
        }
Ejemplo n.º 4
0
        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.
        }
Ejemplo n.º 5
0
        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);
        }
Ejemplo n.º 8
0
        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);
        }
Ejemplo n.º 9
0
        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;
            }
        }
Ejemplo n.º 10
0
        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));
            }
        }
Ejemplo n.º 11
0
        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;
            }
        }
Ejemplo n.º 14
0
        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;
        }
Ejemplo n.º 15
0
        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);
        }
Ejemplo n.º 16
0
        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));
        }
Ejemplo n.º 17
0
        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);
        }
Ejemplo n.º 18
0
        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);
        }
Ejemplo n.º 19
0
        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);
        }
Ejemplo n.º 23
0
 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));
 }
Ejemplo n.º 24
0
        private static void ReportResult(
            Result result,
            IAnalysisLogger logger)
        {
            ReportingDescriptor rule = RuleFactory.GetRuleFromRuleId(result.RuleId);

            logger.Log(rule, result);
        }
Ejemplo n.º 25
0
        private static void ReportResult(Result result, SarifLogger logger)
        {
            ReportingDescriptor rule = RuleFactory.GetRuleFromRuleId(result.RuleId);

            Console.Error.WriteLine(
                result.FormatForVisualStudio(rule));

            logger.Log(rule, result);
        }
Ejemplo n.º 26
0
        private static void ReportResult(
            Result result,
            IAnalysisLogger logger)
        {
#if JSCHEMA_UPGRADED
            ReportingDescriptor rule = RuleFactory.GetRuleFromRuleId(result.RuleId);
            logger.Log(rule, result);
#endif
        }
Ejemplo n.º 27
0
        private static string ConstructFullRuleIdentifier(ReportingDescriptor reportingDescriptor)
        {
            string fullRuleIdentifier = reportingDescriptor.Id;

            if (!string.IsNullOrEmpty(reportingDescriptor.Name))
            {
                fullRuleIdentifier += ": " + reportingDescriptor.Name;
            }
            return(fullRuleIdentifier);
        }
Ejemplo n.º 28
0
 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));
         }
     }
 }
Ejemplo n.º 30
0
        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);
        }