diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs b/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs index eaa836aff..acab90219 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs @@ -63,9 +63,11 @@ internal static class CommonInterest private const RegexOptions FileNamePatternRegexOptions = RegexOptions.IgnoreCase | RegexOptions.Singleline; - private static readonly Regex NegatableTypeOrMemberReferenceRegex = new Regex(@"^(?!)?\[(?[^\[\]\:]+)+\](?:\:\:(?\S+))?\s*$", RegexOptions.Singleline | RegexOptions.CultureInvariant); + private static readonly TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(5); // Prevent expensive CPU hang in Regex.Match if backtracking occurs due to pathological input (see #485). - private static readonly Regex MemberReferenceRegex = new Regex(@"^\[(?[^\[\]\:]+)+\]::(?\S+)\s*$", RegexOptions.Singleline | RegexOptions.CultureInvariant); + private static readonly Regex NegatableTypeOrMemberReferenceRegex = new Regex(@"^(?!)?\[(?[^\[\]\:]+)+\](?:\:\:(?\S+))?\s*$", RegexOptions.Singleline | RegexOptions.CultureInvariant, RegexMatchTimeout); + + private static readonly Regex MemberReferenceRegex = new Regex(@"^\[(?[^\[\]\:]+)+\]::(?\S+)\s*$", RegexOptions.Singleline | RegexOptions.CultureInvariant, RegexMatchTimeout); /// /// An array with '.' as its only element. @@ -84,7 +86,16 @@ internal static IEnumerable ReadTypesAndMembers(AnalyzerOptions a { foreach (string line in ReadAdditionalFiles(analyzerOptions, fileNamePattern, cancellationToken)) { - Match match = NegatableTypeOrMemberReferenceRegex.Match(line); + Match? match = null; + try + { + match = NegatableTypeOrMemberReferenceRegex.Match(line); + } + catch (RegexMatchTimeoutException) + { + throw new InvalidOperationException($"Regex.Match timeout when parsing line: {line}"); + } + if (!match.Success) { throw new InvalidOperationException($"Parsing error on line: {line}"); @@ -175,7 +186,16 @@ internal static IEnumerable ReadLinesFromAdditionalFile(SourceText text) internal static QualifiedMember ParseAdditionalFileMethodLine(string line) { - Match match = MemberReferenceRegex.Match(line); + Match? match = null; + try + { + match = MemberReferenceRegex.Match(line); + } + catch (RegexMatchTimeoutException) + { + throw new InvalidOperationException($"Regex.Match timeout when parsing line: {line}"); + } + if (!match.Success) { throw new InvalidOperationException($"Parsing error on line: {line}");