From 5e419fe7259ce69e20efcca9bec439d45d33adb3 Mon Sep 17 00:00:00 2001 From: Gabe Stocco <98900+gfs@users.noreply.github.com> Date: Wed, 10 Aug 2022 14:03:36 -0700 Subject: [PATCH] Fixes a CodeQL Finding on a null reference error (#496) --- AppInspector.CLI/CLICmdOptions.cs | 1 - AppInspector.RulesEngine/AbstractRuleSet.cs | 43 ++++------ .../OatRegexWithIndexOperation.cs | 2 - .../OatExtensions/WithinClause.cs | 5 +- .../OatExtensions/WithinOperation.cs | 45 ++++++---- AppInspector.RulesEngine/RuleProcessor.cs | 86 +++++++++---------- AppInspector.RulesEngine/Ruleset.cs | 13 --- AppInspector.RulesEngine/TextContainer.cs | 41 +++++---- AppInspector.RulesEngine/TypedRuleSet.cs | 6 -- .../RuleProcessor/WithinClauseTests.cs | 1 - 10 files changed, 117 insertions(+), 126 deletions(-) diff --git a/AppInspector.CLI/CLICmdOptions.cs b/AppInspector.CLI/CLICmdOptions.cs index f7e152b4..0b54691d 100644 --- a/AppInspector.CLI/CLICmdOptions.cs +++ b/AppInspector.CLI/CLICmdOptions.cs @@ -8,7 +8,6 @@ namespace Microsoft.ApplicationInspector.CLI using CommandLine; using Microsoft.ApplicationInspector.Commands; using Microsoft.ApplicationInspector.RulesEngine; - using System; using System.Collections.Generic; /// diff --git a/AppInspector.RulesEngine/AbstractRuleSet.cs b/AppInspector.RulesEngine/AbstractRuleSet.cs index 518e0821..505f6847 100644 --- a/AppInspector.RulesEngine/AbstractRuleSet.cs +++ b/AppInspector.RulesEngine/AbstractRuleSet.cs @@ -3,7 +3,6 @@ using System; using System.Collections.Generic; using System.Globalization; -using System.IO; using System.Linq; using System.Text; using System.Text.RegularExpressions; @@ -73,13 +72,20 @@ public IEnumerable GetUniversalRules() var expression = new StringBuilder("("); foreach (var pattern in rule.Patterns) { - clauses.Add(GenerateClause(pattern, clauseNumber)); - if (clauseNumber > 0) + if (GenerateClause(pattern, clauseNumber) is { } clause) { - expression.Append(" OR "); + clauses.Add(clause); + if (clauseNumber > 0) + { + expression.Append(" OR "); + } + expression.Append(clauseNumber); + clauseNumber++; + } + else + { + _logger.LogWarning("Clause could not be generated from pattern {pattern}", pattern.Pattern); } - expression.Append(clauseNumber); - clauseNumber++; } if (clauses.Count > 0) @@ -122,12 +128,10 @@ public IEnumerable GetUniversalRules() { if (condition.SearchIn?.Equals("finding-only", StringComparison.InvariantCultureIgnoreCase) != false) { - return new WithinClause() + return new WithinClause(subClause) { Label = clauseNumber.ToString(CultureInfo.InvariantCulture), FindingOnly = true, - CustomOperation = "Within", - SubClause = subClause, Invert = condition.NegateFinding }; } @@ -151,56 +155,49 @@ public IEnumerable GetUniversalRules() } if (argList.Count == 2) { - return new WithinClause() + return new WithinClause(subClause) { Label = clauseNumber.ToString(CultureInfo.InvariantCulture), FindingRegion = true, - CustomOperation = "Within", Before = argList[0], After = argList[1], - SubClause = subClause, Invert = condition.NegateFinding }; } } else if (condition.SearchIn.Equals("same-line", StringComparison.InvariantCultureIgnoreCase)) { - return new WithinClause() + return new WithinClause(subClause) { Label = clauseNumber.ToString(CultureInfo.InvariantCulture), SameLineOnly = true, - CustomOperation = "Within", - SubClause = subClause, Invert = condition.NegateFinding }; } else if (condition.SearchIn.Equals("same-file", StringComparison.InvariantCultureIgnoreCase)) { - return new WithinClause() + return new WithinClause(subClause) { Label = clauseNumber.ToString(CultureInfo.InvariantCulture), SameFile = true, - SubClause = subClause, Invert = condition.NegateFinding }; } else if (condition.SearchIn.Equals("only-before", StringComparison.InvariantCultureIgnoreCase)) { - return new WithinClause() + return new WithinClause(subClause) { Label = clauseNumber.ToString(CultureInfo.InvariantCulture), OnlyBefore = true, - SubClause = subClause, Invert = condition.NegateFinding }; } else if (condition.SearchIn.Equals("only-after", StringComparison.InvariantCultureIgnoreCase)) { - return new WithinClause() + return new WithinClause(subClause) { Label = clauseNumber.ToString(CultureInfo.InvariantCulture), OnlyAfter = true, - SubClause = subClause, Invert = condition.NegateFinding }; } @@ -238,8 +235,7 @@ public IEnumerable GetUniversalRules() .InvariantCulture), //important to pattern index identification Data = new List() { pattern.Pattern }, Capture = true, - Arguments = modifiers, - CustomOperation = "RegexWithIndex" + Arguments = modifiers }; } else if (pattern.PatternType == PatternType.RegexWord) @@ -250,7 +246,6 @@ public IEnumerable GetUniversalRules() Data = new List() { $"\\b({pattern.Pattern})\\b" }, Capture = true, Arguments = pattern.Modifiers?.ToList() ?? new List(), - CustomOperation = "RegexWithIndex" }; } } diff --git a/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexOperation.cs b/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexOperation.cs index ea0de733..e4f923b2 100644 --- a/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexOperation.cs +++ b/AppInspector.RulesEngine/OatExtensions/OatRegexWithIndexOperation.cs @@ -1,9 +1,7 @@ using System; -using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Globalization; -using System.Linq; using System.Text.RegularExpressions; using Microsoft.CST.OAT; using Microsoft.CST.OAT.Operations; diff --git a/AppInspector.RulesEngine/OatExtensions/WithinClause.cs b/AppInspector.RulesEngine/OatExtensions/WithinClause.cs index 2b542bb7..c58d9219 100644 --- a/AppInspector.RulesEngine/OatExtensions/WithinClause.cs +++ b/AppInspector.RulesEngine/OatExtensions/WithinClause.cs @@ -6,8 +6,9 @@ namespace Microsoft.ApplicationInspector.RulesEngine.OatExtensions { public class WithinClause : Clause { - public WithinClause(string? field = null) : base(Operation.Custom, field) + public WithinClause(Clause subClause, string? field = null) : base(Operation.Custom, field) { + SubClause = subClause; CustomOperation = "Within"; } @@ -19,6 +20,6 @@ public WithinClause(string? field = null) : base(Operation.Custom, field) public bool FindingOnly { get; set; } public bool SameLineOnly { get; set; } public bool FindingRegion { get; set; } - public Clause SubClause { get; set; } + public Clause SubClause { get; } } } \ No newline at end of file diff --git a/AppInspector.RulesEngine/OatExtensions/WithinOperation.cs b/AppInspector.RulesEngine/OatExtensions/WithinOperation.cs index 2c5a6304..0924ae0c 100644 --- a/AppInspector.RulesEngine/OatExtensions/WithinOperation.cs +++ b/AppInspector.RulesEngine/OatExtensions/WithinOperation.cs @@ -1,9 +1,7 @@ using System; -using System.Collections; using System.Collections.Generic; using System.Globalization; using System.Linq; -using System.Text.RegularExpressions; using Microsoft.CST.OAT; using Microsoft.CST.OAT.Operations; using Microsoft.Extensions.Logging; @@ -15,8 +13,7 @@ public class WithinOperation : OatOperation { public WithinOperation(Analyzer analyzer, ILoggerFactory? loggerFactory = null) : base(Operation.Custom, analyzer) { - _loggerFactory = loggerFactory ?? new NullLoggerFactory(); - _regexEngine = new RegexOperation(analyzer); + _loggerFactory = loggerFactory ?? NullLoggerFactory.Instance; _analyzer = analyzer; CustomOperation = "Within"; OperationDelegate = WithinOperationDelegate; @@ -32,7 +29,7 @@ public OperationResult WithinOperationDelegate(Clause c, object? state1, object? List<(int, Boundary)> failed = new List<(int, Boundary)>(); - foreach (var capture in captures) + foreach (var capture in captures ?? Array.Empty()) { if (capture is TypedClauseCapture> tcc) { @@ -80,7 +77,6 @@ public OperationResult WithinOperationDelegate(Clause c, object? state1, object? Index = startInner, Length = (endInner - startInner) + 1 }; - var theText = tc.GetBoundaryText(bound); return bound; } @@ -131,7 +127,7 @@ OperationResult ProcessLambda(Boundary target) return _analyzer.GetClauseCapture(wc.SubClause, tc, target, captures); } } - return new OperationResult(false, null); + return new OperationResult(false); } public IEnumerable WithinValidationDelegate(CST.OAT.Rule rule, Clause clause) @@ -166,16 +162,11 @@ public IEnumerable WithinValidationDelegate(CST.OAT.Rule rule, Clause rule, clause); } } - if (wc.Data?.Any() ?? false) + if (wc.Data.Any()) { - yield return new Violation($"Don't provide data directly. Instead use SubClause..", rule, clause); + yield return new Violation($"Don't provide data directly. Instead use SubClause.", rule, clause); } - foreach (var datum in wc.Data ?? new List()) - { - yield return new Violation($"Data in WithinClause is ignored. Use SubClause. Data {datum} found in Rule {rule.Name} Clause {clause.Label ?? rule.Clauses.IndexOf(clause).ToString(CultureInfo.InvariantCulture)} is not a valid regex.", rule, clause); - } - var subOp = _analyzer .GetOperation(wc.SubClause.Key.Operation, wc.SubClause.Key.CustomOperation); @@ -189,16 +180,38 @@ public IEnumerable WithinValidationDelegate(CST.OAT.Rule rule, Clause { yield return violation; } + + if (wc.SubClause is OatRegexWithIndexClause oatRegexWithIndexClause) + { + if ((oatRegexWithIndexClause.JsonPaths?.Any() ?? false) || + (oatRegexWithIndexClause.XPaths?.Any() ?? false)) + { + if (wc.FindingOnly || wc.SameLineOnly || wc.FindingRegion || wc.OnlyAfter || wc.OnlyBefore) + { + yield return new Violation($"When providing JSONPaths or XPaths must use same-file region.", rule, clause); + } + } + } + if (wc.SubClause is OatSubstringIndexClause oatSubstringIndexClause) + { + if ((oatSubstringIndexClause.JsonPaths?.Any() ?? false) || + (oatSubstringIndexClause.XPaths?.Any() ?? false)) + { + if (wc.FindingOnly || wc.SameLineOnly || wc.FindingRegion || wc.OnlyAfter || wc.OnlyBefore) + { + yield return new Violation($"When providing JSONPaths or XPaths must use same-file region.", rule, clause); + } + } + } } } else { - yield return new Violation($"Rule {rule.Name ?? "Null Rule Name"} clause {clause.Label ?? rule.Clauses.IndexOf(clause).ToString(CultureInfo.InvariantCulture)} is not a WithinClause", rule, clause); + yield return new Violation($"Rule {rule.Name} clause {clause.Label ?? rule.Clauses.IndexOf(clause).ToString(CultureInfo.InvariantCulture)} is not a WithinClause", rule, clause); } } - private readonly RegexOperation _regexEngine; private readonly ILoggerFactory _loggerFactory; private readonly Analyzer _analyzer; } diff --git a/AppInspector.RulesEngine/RuleProcessor.cs b/AppInspector.RulesEngine/RuleProcessor.cs index babfac65..aa98a2f3 100644 --- a/AppInspector.RulesEngine/RuleProcessor.cs +++ b/AppInspector.RulesEngine/RuleProcessor.cs @@ -30,7 +30,7 @@ public RuleProcessorOptions() public Confidence ConfidenceFilter { get; set; } = Confidence.Unspecified | Confidence.Low | Confidence.Medium | Confidence.High; public Severity SeverityFilter { get; set; } = Severity.Critical | Severity.Important | Severity.Moderate | Severity.BestPractice; public ILoggerFactory? LoggerFactory { get; set; } - public bool AllowAllTagsInBuildFiles { get; set; } = false; + public bool AllowAllTagsInBuildFiles { get; set; } public bool EnableCache { get; set; } = true; public Languages Languages { get; set; } = new(); } @@ -44,7 +44,7 @@ public class RuleProcessor private readonly RuleProcessorOptions _opts; private readonly ILogger _logger; - private readonly Analyzer analyzer; + private readonly Analyzer _analyzer; private readonly AbstractRuleSet _ruleset; private readonly Languages _languages; private readonly ConcurrentDictionary> _fileRulesCache = new(); @@ -68,11 +68,11 @@ public RuleProcessor(AbstractRuleSet rules, RuleProcessorOptions opts) { _opts = opts; _logger = opts.LoggerFactory?.CreateLogger() ?? NullLogger.Instance; - _languages = opts.Languages ?? new(); + _languages = opts.Languages; _ruleset = rules; EnableCache = true; - analyzer = new ApplicationInspectorAnalyzer(_opts.LoggerFactory); + _analyzer = new ApplicationInspectorAnalyzer(_opts.LoggerFactory); } private static string ExtractDependency(TextContainer? text, int startIndex, string? pattern, string? language) @@ -87,11 +87,11 @@ private static string ExtractDependency(TextContainer? text, int startIndex, str if (-1 != startIndex && -1 != endIndex) { rawResult = text.FullContent[startIndex..endIndex].Trim(); - Regex regex = new(pattern ?? string.Empty); + Regex regex = new(pattern); MatchCollection matches = regex.Matches(rawResult); //remove surrounding import or trailing comments - if (matches?.Any() == true) + if (matches.Any()) { foreach (Match? match in matches) { @@ -104,7 +104,7 @@ private static string ExtractDependency(TextContainer? text, int startIndex, str } else if (parseValues.Length > 1) { - rawResult = parseValues[1].Trim(); //should be value; time will tell if fullproof + rawResult = parseValues[1].Trim(); } } else if (match?.Groups.Count > 1)//handles cases like include @@ -140,7 +140,7 @@ public List AnalyzeFile(TextContainer textContainer, FileEntry file var rules = GetRulesForFile(languageInfo, fileEntry, tagsToIgnore); List resultsList = new(); - var caps = analyzer.GetCaptures(rules, textContainer); + var caps = _analyzer.GetCaptures(rules, textContainer); foreach (var ruleCapture in caps) { // If we had a WithinClause we only want the captures that passed the within filter. @@ -159,7 +159,7 @@ List ProcessBoundary(ClauseCapture cap) { if (ruleCapture.Rule is ConvertedOatRule oatRule) { - if (tcc?.Result is List<(int, Boundary)> captureResults) + if (tcc.Result is { } captureResults) { foreach (var match in captureResults) { @@ -170,26 +170,25 @@ List ProcessBoundary(ClauseCapture cap) { continue; } - if (!_opts.ConfidenceFilter.HasFlag(oatRule.AppInspectorRule.Patterns[patternIndex].Confidence)) { continue; } - Location StartLocation = textContainer.GetLocation(boundary.Index); - Location EndLocation = textContainer.GetLocation(boundary.Index + boundary.Length); + Location startLocation = textContainer.GetLocation(boundary.Index); + Location endLocation = textContainer.GetLocation(boundary.Index + boundary.Length); MatchRecord newMatch = new(oatRule.AppInspectorRule) { FileName = fileEntry.FullPath, FullTextContainer = textContainer, LanguageInfo = languageInfo, Boundary = boundary, - StartLocationLine = StartLocation.Line, - StartLocationColumn = StartLocation.Column, - EndLocationLine = EndLocation.Line != 0 ? EndLocation.Line : StartLocation.Line + 1, //match is on last line - EndLocationColumn = EndLocation.Column, + StartLocationLine = startLocation.Line, + StartLocationColumn = startLocation.Column, + EndLocationLine = endLocation.Line != 0 ? endLocation.Line : startLocation.Line + 1, //match is on last line + EndLocationColumn = endLocation.Column, MatchingPattern = oatRule.AppInspectorRule.Patterns[patternIndex], - Excerpt = numLinesContext > 0 ? ExtractExcerpt(textContainer, StartLocation.Line, numLinesContext) : string.Empty, + Excerpt = numLinesContext > 0 ? ExtractExcerpt(textContainer, startLocation.Line, numLinesContext) : string.Empty, Sample = numLinesContext > -1 ? ExtractTextSample(textContainer.FullContent, boundary.Index, boundary.Length) : string.Empty }; @@ -217,8 +216,8 @@ List ProcessBoundary(ClauseCapture cap) foreach (MatchRecord om in resultsList.FindAll(x => x.Rule?.Id == idsToOverride)) { // If the overridden match is a subset of the overriding match - if (om.Boundary?.Index >= m.Boundary?.Index && - om.Boundary?.Index <= m.Boundary?.Index + m.Boundary?.Length) + if (om.Boundary.Index >= m.Boundary.Index && + om.Boundary.Index <= m.Boundary.Index + m.Boundary.Length) { removes.Add(om); } @@ -243,7 +242,7 @@ List ProcessBoundary(ClauseCapture cap) /// A List of the matches against the Rules the processor is configured with. public List AnalyzeFile(string contents, FileEntry fileEntry, LanguageInfo languageInfo, IEnumerable? tagsToIgnore = null, int numLinesContext = 3) { - TextContainer textContainer = new(contents, languageInfo.Name, _languages, _opts.LoggerFactory?.CreateLogger() ?? NullLogger.Instance); + TextContainer textContainer = new(contents, languageInfo.Name, _languages, _opts.LoggerFactory ?? NullLoggerFactory.Instance); return AnalyzeFile(textContainer, fileEntry, languageInfo, tagsToIgnore, numLinesContext); } @@ -294,8 +293,8 @@ public async Task> AnalyzeFileAsync(FileEntry fileEntry, Langu using var sr = new StreamReader(fileEntry.Content); - TextContainer textContainer = new(await sr.ReadToEndAsync().ConfigureAwait(false), languageInfo.Name, _languages, _opts.LoggerFactory?.CreateLogger() ?? NullLogger.Instance); - foreach (var ruleCapture in analyzer.GetCaptures(rules, textContainer)) + TextContainer textContainer = new(await sr.ReadToEndAsync().ConfigureAwait(false), languageInfo.Name, _languages, _opts.LoggerFactory ?? NullLoggerFactory.Instance); + foreach (var ruleCapture in _analyzer.GetCaptures(rules, textContainer)) { // If we had a WithinClause we only want the captures that passed the within filter. var filteredCaptures = ruleCapture.Captures.Any(x => x.Clause is WithinClause) @@ -317,7 +316,7 @@ List ProcessBoundary(ClauseCapture cap) { if (ruleCapture.Rule is ConvertedOatRule oatRule) { - if (tcc?.Result is List<(int, Boundary)> captureResults) + if (tcc.Result is { } captureResults) { foreach (var match in captureResults) { @@ -341,18 +340,18 @@ List ProcessBoundary(ClauseCapture cap) continue; } - Location StartLocation = textContainer.GetLocation(boundary.Index); - Location EndLocation = textContainer.GetLocation(boundary.Index + boundary.Length); + Location startLocation = textContainer.GetLocation(boundary.Index); + Location endLocation = textContainer.GetLocation(boundary.Index + boundary.Length); MatchRecord newMatch = new(oatRule.AppInspectorRule) { FileName = fileEntry.FullPath, FullTextContainer = textContainer, LanguageInfo = languageInfo, Boundary = boundary, - StartLocationLine = StartLocation.Line, - EndLocationLine = EndLocation.Line != 0 ? EndLocation.Line : StartLocation.Line + 1, //match is on last line + StartLocationLine = startLocation.Line, + EndLocationLine = endLocation.Line != 0 ? endLocation.Line : startLocation.Line + 1, //match is on last line MatchingPattern = oatRule.AppInspectorRule.Patterns[patternIndex], - Excerpt = numLinesContext > 0 ? ExtractExcerpt(textContainer, StartLocation.Line, numLinesContext) : string.Empty, + Excerpt = numLinesContext > 0 ? ExtractExcerpt(textContainer, startLocation.Line, numLinesContext) : string.Empty, Sample = numLinesContext > -1 ? ExtractTextSample(textContainer.FullContent, boundary.Index, boundary.Length) : string.Empty }; @@ -372,7 +371,7 @@ List ProcessBoundary(ClauseCapture cap) List removes = new(); - foreach (MatchRecord m in resultsList.Where(x => x.Rule.Overrides?.Length > 0)) + foreach (MatchRecord m in resultsList.Where(x => x.Rule?.Overrides?.Length > 0)) { if (cancellationToken?.IsCancellationRequested is true) { @@ -381,10 +380,10 @@ List ProcessBoundary(ClauseCapture cap) foreach (string ovrd in m.Rule?.Overrides ?? Array.Empty()) { // Find all overriden rules and mark them for removal from issues list - foreach (MatchRecord om in resultsList.FindAll(x => x.Rule.Id == ovrd)) + foreach (MatchRecord om in resultsList.FindAll(x => x.Rule?.Id == ovrd)) { - if (om.Boundary?.Index >= m.Boundary?.Index && - om.Boundary?.Index <= m.Boundary?.Index + m.Boundary?.Length) + if (om.Boundary.Index >= m.Boundary.Index && + om.Boundary.Index <= m.Boundary.Index + m.Boundary.Length) { removes.Add(om); } @@ -400,9 +399,9 @@ List ProcessBoundary(ClauseCapture cap) /// - /// Filters the rules for those matching the content type. Resolves all the overrides + /// Filters the rules for those matching the specified language. /// - /// Languages to filter rules for + /// Language to filter rules for /// List of rules private IEnumerable GetRulesByLanguage(string language) { @@ -412,7 +411,7 @@ private IEnumerable GetRulesByLanguage(string language) return _languageRulesCache[language]; } - IEnumerable filteredRules = _ruleset.ByLanguage(language); + IEnumerable filteredRules = _ruleset.ByLanguage(language).ToArray(); if (EnableCache) { @@ -423,9 +422,8 @@ private IEnumerable GetRulesByLanguage(string language) } /// - /// Filters the rules for those matching the content type. Resolves all the overrides + /// Get all rules that apply to all files. /// - /// Languages to filter rules for /// List of rules private IEnumerable GetUniversalRules() { @@ -445,23 +443,23 @@ private IEnumerable GetUniversalRules() } /// - /// Filters the rules for those matching the content type. Resolves all the overrides + /// Filters the rules for those matching the filename. /// - /// Languages to filter rules for + /// Filename to filter for /// List of rules - private IEnumerable GetRulesByFileName(string input) + private IEnumerable GetRulesByFileName(string fileName) { if (EnableCache) { - if (_fileRulesCache.ContainsKey(input)) - return _fileRulesCache[input]; + if (_fileRulesCache.ContainsKey(fileName)) + return _fileRulesCache[fileName]; } - IEnumerable filteredRules = _ruleset.ByFilename(input); + IEnumerable filteredRules = _ruleset.ByFilename(fileName).ToArray(); if (EnableCache) { - _fileRulesCache.TryAdd(input, filteredRules); + _fileRulesCache.TryAdd(fileName, filteredRules); } return filteredRules; diff --git a/AppInspector.RulesEngine/Ruleset.cs b/AppInspector.RulesEngine/Ruleset.cs index 09c25d56..eb7c8911 100644 --- a/AppInspector.RulesEngine/Ruleset.cs +++ b/AppInspector.RulesEngine/Ruleset.cs @@ -1,22 +1,9 @@ // Copyright (C) Microsoft. All rights reserved. Licensed under the MIT License. -using Microsoft.ApplicationInspector.RulesEngine.OatExtensions; -using Newtonsoft.Json; - namespace Microsoft.ApplicationInspector.RulesEngine { - using Microsoft.CST.OAT; using Microsoft.Extensions.Logging; - using Microsoft.Extensions.Logging.Abstractions; - using System; - using System.Collections; - using System.Collections.Generic; - using System.Globalization; - using System.IO; - using System.Linq; - using System.Text; - using System.Text.RegularExpressions; /// /// Default class to use to store Application Inspector objects. diff --git a/AppInspector.RulesEngine/TextContainer.cs b/AppInspector.RulesEngine/TextContainer.cs index 939c6841..30f27506 100644 --- a/AppInspector.RulesEngine/TextContainer.cs +++ b/AppInspector.RulesEngine/TextContainer.cs @@ -13,7 +13,6 @@ namespace Microsoft.ApplicationInspector.RulesEngine using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; - using System.Xml; using System.Xml.XPath; /// /// Class to handle text as a searchable container @@ -26,9 +25,9 @@ public class TextContainer /// Text to work with /// The language of the test /// An instance of the class containing the information for language mapping to use. - public TextContainer(string content, string language, Languages languages, ILogger? logger = null) + public TextContainer(string content, string language, Languages languages, ILoggerFactory? loggerFactory = null) { - _logger = logger ?? NullLogger.Instance; + _logger = loggerFactory?.CreateLogger() ?? NullLogger.Instance; Language = language; FullContent = content; LineEnds = new List() { 0 }; @@ -86,23 +85,31 @@ public TextContainer(string content, string language, Languages languages, ILogg IList values = selector.Select(_jsonDocument.RootElement); var field = typeof(JsonElement).GetField("_idx", BindingFlags.NonPublic | BindingFlags.Instance); - - foreach (JsonElement ele in values) + if (field is null) + { + _logger.LogWarning("Failed to access _idx field of JsonElement."); + } + else { - // Private access hack - // The idx field is the start of the JSON element, including markup that isn't directly part of the element itself - var idx = (int)field!.GetValue(ele); - var eleString = ele.ToString(); - if (eleString is { } denulledString) + foreach (JsonElement ele in values) { - var location = new Boundary() + // Private access hack + // The idx field is the start of the JSON element, including markup that isn't directly part of the element itself + if (field.GetValue(ele) is int idx) { - // Adjust the index to the start of the actual element - Index = FullContent[idx..].IndexOf(denulledString, StringComparison.Ordinal) + idx, - Length = eleString.Length - }; - yield return (eleString, location); - } + var eleString = ele.ToString(); + if (eleString is { } denulledString) + { + var location = new Boundary() + { + // Adjust the index to the start of the actual element + Index = FullContent[idx..].IndexOf(denulledString, StringComparison.Ordinal) + idx, + Length = eleString.Length + }; + yield return (eleString, location); + } + } + } } } } diff --git a/AppInspector.RulesEngine/TypedRuleSet.cs b/AppInspector.RulesEngine/TypedRuleSet.cs index 64c9a9c6..26af87bc 100644 --- a/AppInspector.RulesEngine/TypedRuleSet.cs +++ b/AppInspector.RulesEngine/TypedRuleSet.cs @@ -1,13 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Globalization; using System.IO; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using Microsoft.ApplicationInspector.RulesEngine.OatExtensions; -using Microsoft.CST.OAT; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging.Abstractions; using Newtonsoft.Json; diff --git a/AppInspector.Tests/RuleProcessor/WithinClauseTests.cs b/AppInspector.Tests/RuleProcessor/WithinClauseTests.cs index 19afff37..bb70e473 100644 --- a/AppInspector.Tests/RuleProcessor/WithinClauseTests.cs +++ b/AppInspector.Tests/RuleProcessor/WithinClauseTests.cs @@ -2,7 +2,6 @@ using System.Diagnostics.CodeAnalysis; using System.IO; using System.Linq; -using Microsoft.ApplicationInspector.Commands; using Microsoft.ApplicationInspector.Logging; using Microsoft.ApplicationInspector.RulesEngine; using Microsoft.ApplicationInspector.RulesEngine.OatExtensions;