diff --git a/docs/Producing effective SARIF.md b/docs/Producing effective SARIF.md index d61e8f995..a2c166f17 100644 --- a/docs/Producing effective SARIF.md +++ b/docs/Producing effective SARIF.md @@ -313,13 +313,13 @@ The SARIF standard was developed over several years, and many intermediate versi The properties of a result's 'message' property must be consistent with the properties of the rule that the result refers to. -When a result's 'message' object uses the 'id' and 'arguments' properties (which, by the way, is recommended: see SARIF2002.ProvideMessageArguments), it must ensure that the rule actually defines a message string with that id, and that 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{3}', then the 'arguments' array must contain at least 4 elements. +When a result's 'message' object uses the 'id' and 'arguments' properties (which, by the way, is recommended: see SARIF2002.ProvideMessageArguments), it must ensure that the rule actually defines a message string with that id, and that 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must contain at least 4 elements. #### Messages ##### `SupplyEnoughMessageArguments`: error -{0}: The message with id '{1}' in rule '{2}' requires {3} arguments, but the 'arguments' array in this message object has only {4} elements. When a tool creates a result message that use the 'id' and 'arguments' properties, it must ensure that the 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must contain 4 elements. +{0}: The message with id '{1}' in rule '{2}' requires '{3}' arguments, but the 'arguments' array in this message object has only '{4}' element(s). When a tool creates a result message that use the 'id' and 'arguments' properties, it must ensure that the 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must contain 4 elements. ##### `MessageIdMustExist`: error diff --git a/src/Sarif.Multitool/Rules/RuleResources.Designer.cs b/src/Sarif.Multitool/Rules/RuleResources.Designer.cs index 32fe6ecaf..57d1f078c 100644 --- a/src/Sarif.Multitool/Rules/RuleResources.Designer.cs +++ b/src/Sarif.Multitool/Rules/RuleResources.Designer.cs @@ -366,7 +366,7 @@ internal static string SARIF1012_MessageArgumentsMustBeConsistentWithRule_Error_ } /// - /// Looks up a localized string similar to {0}: The message with id '{1}' in rule '{2}' requires {3} arguments, but the 'arguments' array in this message object has only {4} elements. When a tool creates a result message that use the 'id' and 'arguments' properties, it must ensure that the 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must contain 4 [rest of string was truncated]";. + /// Looks up a localized string similar to {0}: The message with id '{1}' in rule '{2}' requires '{3}' arguments, but the 'arguments' array in this message object has only '{4}' element(s). When a tool creates a result message that use the 'id' and 'arguments' properties, it must ensure that the 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must con [rest of string was truncated]";. /// internal static string SARIF1012_MessageArgumentsMustBeConsistentWithRule_Error_SupplyEnoughMessageArguments_Text { get { diff --git a/src/Sarif.Multitool/Rules/RuleResources.resx b/src/Sarif.Multitool/Rules/RuleResources.resx index 93785dda9..6f2e7d0d1 100644 --- a/src/Sarif.Multitool/Rules/RuleResources.resx +++ b/src/Sarif.Multitool/Rules/RuleResources.resx @@ -316,12 +316,12 @@ Many tools follow a conventional format for the 'reportingDescriptor.id' propert {0}: This message object refers to the message with id '{1}' in rule '{2}', but that rule does not define a message with that id. When a tool creates a result message that uses the 'id' property, it must ensure that the specified rule actually has a message with that id. - {0}: The message with id '{1}' in rule '{2}' requires {3} arguments, but the 'arguments' array in this message object has only {4} elements. When a tool creates a result message that use the 'id' and 'arguments' properties, it must ensure that the 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must contain 4 elements. + {0}: The message with id '{1}' in rule '{2}' requires '{3}' arguments, but the 'arguments' array in this message object has only '{4}' element(s). When a tool creates a result message that use the 'id' and 'arguments' properties, it must ensure that the 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must contain 4 elements. The properties of a result's 'message' property must be consistent with the properties of the rule that the result refers to. -When a result's 'message' object uses the 'id' and 'arguments' properties (which, by the way, is recommended: see SARIF2002.ProvideMessageArguments), it must ensure that the rule actually defines a message string with that id, and that 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{3}', then the 'arguments' array must contain at least 4 elements. +When a result's 'message' object uses the 'id' and 'arguments' properties (which, by the way, is recommended: see SARIF2002.ProvideMessageArguments), it must ensure that the rule actually defines a message string with that id, and that 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must contain at least 4 elements. Placeholder_SARIF2013_ProvideEmbeddedFileContent_Note_Default_Text diff --git a/src/Sarif.Multitool/Rules/SARIF1012.MessageArgumentsMustBeConsistentWithRule.cs b/src/Sarif.Multitool/Rules/SARIF1012.MessageArgumentsMustBeConsistentWithRule.cs index 66814707e..c33015e49 100644 --- a/src/Sarif.Multitool/Rules/SARIF1012.MessageArgumentsMustBeConsistentWithRule.cs +++ b/src/Sarif.Multitool/Rules/SARIF1012.MessageArgumentsMustBeConsistentWithRule.cs @@ -35,7 +35,7 @@ public class MessageArgumentsMustBeConsistentWithRule : SarifValidationSkimmerBa public override FailureLevel DefaultLevel => FailureLevel.Error; - private static readonly Regex s_replacementSequenceRegex = new Regex(@"\{(\d+)\}", RegexOptions.Compiled | RegexOptions.CultureInvariant); + private static readonly Regex s_replacementSequenceRegex = new Regex(@"\{(?\d+)\}", RegexOptions.Compiled | RegexOptions.CultureInvariant); private IList currentRules; private Run run; @@ -69,11 +69,12 @@ protected override void Analyze(Result result, string resultPointer) // A message with the specified key is present in the rule. Check if the result supplied enough arguments. string messageText = rule.MessageStrings[result.Message.Id].Text; - int placeholderMaxPosition = PlaceholderMaxPosition(messageText); - if (placeholderMaxPosition > (result.Message.Arguments?.Count ?? 0)) + int numArgsRequired = GetNumArgsRequired(messageText); + int numArgsPresent = result.Message.Arguments?.Count ?? 0; + if (numArgsRequired > numArgsPresent) { - // {0}: The message with id '{1}' in rule '{2}' requires {3} arguments, but the - // 'arguments' array in this message object has only {4} elements. When a tool + // {0}: The message with id '{1}' in rule '{2}' requires '{3}' arguments, but the + // 'arguments' array in this message object has only '{4}' element(s). When a tool // creates a result message that use the 'id' and 'arguments' properties, it must // ensure that the 'arguments' array has enough elements to provide values for every // replacement sequence in the message specified by 'id'. For example, if the highest @@ -82,16 +83,15 @@ protected override void Analyze(Result result, string resultPointer) LogResult( resultPointer, nameof(RuleResources.SARIF1012_MessageArgumentsMustBeConsistentWithRule_Error_SupplyEnoughMessageArguments_Text), - result.Message.Arguments.Count.ToString(), result.Message.Id, result.ResolvedRuleId(run) ?? "null", - placeholderMaxPosition.ToString(), - messageText); + numArgsRequired.ToString(), + result.Message.Arguments.Count.ToString()); } } } - private int PlaceholderMaxPosition(string text) + private int GetNumArgsRequired(string text) { int max = -1; foreach (Match match in s_replacementSequenceRegex.Matches(text)) @@ -100,7 +100,7 @@ private int PlaceholderMaxPosition(string text) max = Math.Max(max, index); } - return max++; + return max + 1; } } } diff --git a/src/Test.FunctionalTests.Sarif/TestData/Multitool/ValidateCommand/ExpectedOutputs/SARIF1012.MessageArgumentsMustBeConsistentWithRule_Invalid.sarif b/src/Test.FunctionalTests.Sarif/TestData/Multitool/ValidateCommand/ExpectedOutputs/SARIF1012.MessageArgumentsMustBeConsistentWithRule_Invalid.sarif index f5803920c..f3d57881b 100644 --- a/src/Test.FunctionalTests.Sarif/TestData/Multitool/ValidateCommand/ExpectedOutputs/SARIF1012.MessageArgumentsMustBeConsistentWithRule_Invalid.sarif +++ b/src/Test.FunctionalTests.Sarif/TestData/Multitool/ValidateCommand/ExpectedOutputs/SARIF1012.MessageArgumentsMustBeConsistentWithRule_Invalid.sarif @@ -14,14 +14,14 @@ "text": "The properties of a result's 'message' property must be consistent with the properties of the rule that the result refers to." }, "fullDescription": { - "text": "The properties of a result's 'message' property must be consistent with the properties of the rule that the result refers to.\r\n\r\nWhen a result's 'message' object uses the 'id' and 'arguments' properties (which, by the way, is recommended: see SARIF2002.ProvideMessageArguments), it must ensure that the rule actually defines a message string with that id, and that 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{3}', then the 'arguments' array must contain at least 4 elements." + "text": "The properties of a result's 'message' property must be consistent with the properties of the rule that the result refers to.\r\n\r\nWhen a result's 'message' object uses the 'id' and 'arguments' properties (which, by the way, is recommended: see SARIF2002.ProvideMessageArguments), it must ensure that the rule actually defines a message string with that id, and that 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must contain at least 4 elements." }, "messageStrings": { "Error_MessageIdMustExist": { "text": "{0}: This message object refers to the message with id '{1}' in rule '{2}', but that rule does not define a message with that id. When a tool creates a result message that uses the 'id' property, it must ensure that the specified rule actually has a message with that id." }, "Error_SupplyEnoughMessageArguments": { - "text": "{0}: The message with id '{1}' in rule '{2}' requires {3} arguments, but the 'arguments' array in this message object has only {4} elements. When a tool creates a result message that use the 'id' and 'arguments' properties, it must ensure that the 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must contain 4 elements." + "text": "{0}: The message with id '{1}' in rule '{2}' requires '{3}' arguments, but the 'arguments' array in this message object has only '{4}' element(s). When a tool creates a result message that use the 'id' and 'arguments' properties, it must ensure that the 'arguments' array has enough elements to provide values for every replacement sequence in the message specified by 'id'. For example, if the highest numbered replacement sequence in the specified message string is '{{3}}', then the 'arguments' array must contain 4 elements." } }, "helpUri": "http://docs.oasis-open.org/sarif/sarif/v2.1.0/sarif-v2.1.0.html" @@ -69,6 +69,34 @@ } ], "results": [ + { + "ruleId": "SARIF1012", + "ruleIndex": 0, + "level": "error", + "message": { + "id": "Error_SupplyEnoughMessageArguments", + "arguments": [ + "runs[0].results[0]", + "DoesExist", + "TEST1001", + "2", + "1" + ] + }, + "locations": [ + { + "physicalLocation": { + "artifactLocation": { + "index": 0 + }, + "region": { + "startLine": 26, + "startColumn": 9 + } + } + } + ] + }, { "ruleId": "SARIF1012", "ruleIndex": 0,