madskristensen / EditorConfigLanguage

A Visual Studio extension
Other
129 stars 37 forks source link

Catastrophic Backtracking (100% CPU + VS hang) in EditorConfigDocument.ParseAsync's _suppress Regex, caused by comma in input #113

Open daiplusplus opened 3 years ago

daiplusplus commented 3 years ago

Installed product versions

Description

(Updated) Steps to recreate

After some digging, I found out the _suppress regex can get stuck on certain inputs. Here's a reliable repro I've made in Linqpad 6:

// Copied from https://github.com/madskristensen/EditorConfigLanguage/blob/ebec9b5d3069c9c6a0adbdcf2e642ef2d9d8317f/src/Parser/EditorConfigDocumentParser.cs
Regex suppressRegex = new Regex(@"^(?<comment>#\s*suppress\s*):?\s*(?<errors>(\w{0,5}\s*)+)$", RegexOptions.IgnoreCase);

String goodLine = @"# Suppressed because we do use antiforgery tokens as configured in Startup.cs";
Match goodMatch = suppressRegex.Match( goodLine ); // Works fine
goodMatch.Dump();

String badLine = @"# Suppressed because we do use antiforgery tokens, as configured in Startup.cs";
Match badMatch = suppressRegex.Match( badLine ); // <-- Program will get stuck here.
badMatch.Dump();

I tried it on Regex101.com on the same input data and it reported a Catastrophic Backtracking error.

(Real-life) Steps to recreate

  1. Have an editor config like this:

    root = true
    
    # All files 
    [*]
    indent_style = tab
    
    [*.csproj]
    indent_style = space
    indent_size = 2
    
    # Code files
    [*.cs]
    indent_size = 4
    insert_final_newline = true
    charset = utf-8
    
    # CA1055: URI return values should not be strings
    dotnet_diagnostic.CA1055.severity = silent
    # CA1056: URI properties should not be strings
    dotnet_diagnostic.CA1056.severity = silent
    
    # CA5395: Action method needs to specify the HTTP request kind explictly
    # https://github.com/dotnet/aspnetcore/issues/33102
    dotnet_diagnostic.CA5395.severity = none
    
    # CA1707: Identifiers should not contain underscores
    dotnet_diagnostic.CA1707.severity = none
    
    # CA5391: Use antiforgery tokens in ASP.NET Core MVC controllers
    dotnet_code_quality.CA5391.exclude_aspnet_core_mvc_controllerbase = true
  2. Manually type a new comment line underneath the # CA5391 line (and before dotnet_code_quality.CA5391):

    # Suppressed because we do use antiforgery tokens as configured in Startup.cs
  3. Insert a comma after "tokens" and before "as configured":

    # Suppressed because we do use antiforgery tokens, as configured in Startup.cs
  4. devenv.exe will now hog your CPU.

Stack traces

image

>   System.dll!System.Text.RegularExpressions.RegexInterpreter.Go() Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.RegexRunner.Scan(System.Text.RegularExpressions.Regex regex, string text, int textbeg, int textend, int textstart, int prevlen, bool quick = false, System.TimeSpan timeout)  Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.Regex.Run(bool quick, int prevlen, string input, int beginning, int length, int startat)  Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.Regex.Match(string input, int startat)    Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.Regex.Match(string input) Unknown Non-user code. Skipped loading symbols.
    EditorConfig.dll!EditorConfig.EditorConfigDocument.ParseAsync.AnonymousMethod__26_0()   Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.InnerInvoke()  Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.Execute()  Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj)   Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot = Id = 1189516, Status = Running, Method = Inspecting the state of an object in the debuggee of type System.Delegate is not supported in this context.) Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()    Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Unknown Non-user code. Skipped loading symbols.

and

>   System.dll!System.Text.RegularExpressions.RegexCharClass.CharInCategoryGroup(char ch, System.Globalization.UnicodeCategory chcategory = LowercaseLetter, string category = "\0\0\n\0\u0002\u0004\u0005\u0003\u0001\u0006\t\u0013\0", ref int i = 7) Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.RegexCharClass.CharInCategory(char ch, string set = "\0\0\n\0\u0002\u0004\u0005\u0003\u0001\u0006\t\u0013\0", int start, int mySetLength, int myCategoryLength)   Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.RegexCharClass.CharInClassInternal(char ch, string set, int start, int mySetLength, int myCategoryLength) Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.RegexCharClass.CharInClassRecursive(char ch, string set, int start)   Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.RegexCharClass.CharInClass(char ch, string set)   Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.RegexInterpreter.Go() Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.RegexRunner.Scan(System.Text.RegularExpressions.Regex regex, string text, int textbeg, int textend, int textstart, int prevlen, bool quick = false, System.TimeSpan timeout)  Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.Regex.Run(bool quick, int prevlen, string input, int beginning, int length, int startat)  Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.Regex.Match(string input, int startat)    Unknown Non-user code. Skipped loading symbols.
    System.dll!System.Text.RegularExpressions.Regex.Match(string input) Unknown Non-user code. Skipped loading symbols.
    EditorConfig.dll!EditorConfig.EditorConfigDocument.ParseAsync.AnonymousMethod__26_0()   Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.InnerInvoke()  Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.Execute()  Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.ExecutionContextCallback(object obj)   Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool preserveSyncCtx)   Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.ExecuteWithThreadLocal(ref System.Threading.Tasks.Task currentTaskSlot = Id = 1189518, Status = Running, Method = "Void <ParseAsync>b__26_0()")    Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.ExecuteEntry(bool bPreventDoubleExecution) Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.Tasks.Task.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem() Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading.ThreadPoolWorkQueue.Dispatch()    Unknown Non-user code. Skipped loading symbols.
    mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCallback() Unknown Non-user code. Skipped loading symbols.