Skip to content

Do not crash on an invalid regex in the .editorconfig (MA0003, MA0104) - #1345

Merged
meziantou merged 1 commit into
mainfrom
feature/meziantou-analyzer-1329-c3e6da
Aug 26, 2026
Merged

Do not crash on an invalid regex in the .editorconfig (MA0003, MA0104)#1345
meziantou merged 1 commit into
mainfrom
feature/meziantou-analyzer-1329-c3e6da

Conversation

@meziantou

Copy link
Copy Markdown
Owner

Fixes #1329

A regex coming from the .editorconfig was passed straight to new Regex(...), with no try/catch and with Timeout.InfiniteTimeSpan. One typo in a shared .editorconfig (MA0104.namespaces_regex = [) crashed the analyzer with AD0001 on every build, and a pattern with catastrophic backtracking would hang the compilation thread instead of failing.

What changed

RegexCache now owns both concerns:

  • The pattern is parsed once, ArgumentException is caught, and the failure (plus its message) is cached, so an invalid pattern never throws and is never re-parsed.
  • A fixed 1 second match timeout replaces Timeout.InfiniteTimeSpan, and IsMatch catches RegexMatchTimeoutException, so a catastrophic pattern degrades to "no match" instead of hanging or crashing. RegexOptions.NonBacktracking was not an option: the analyzer also targets netstandard2.0.
  • The timeout is no longer part of the cache key, since callers cannot choose it anymore.

Call sites

  • MA0104: an invalid namespaces_regex (or the legacy namepaces_regex) falls back to the default ^System($|\.).
  • MA0003: an invalid excluded_methods_regex excludes no method.
  • MA0003 no longer passes RegexOptions.Compiled for a pattern matched a handful of times per compilation: RegexCache is a process-lifetime static, so the compiled entries were pinning emitted IL that is never reclaimed. The cache is still unbounded, but it now only holds interpreted Regex objects keyed by the few patterns of an .editorconfig.

New rule MA0220 - The configured regular expression is not valid

Silently ignoring the value would leave the user with a rule that does not behave as configured and no way to know why, so the invalid values are reported:

MA0220: The value of 'MA0104.namespaces_regex' is not a valid regular expression: Invalid pattern '[' at offset 1. Unterminated [] set.

It is a dedicated analyzer with a single RegisterCompilationAction, not a diagnostic reported by MA0003/MA0104 themselves, because the error is not tied to a symbol or a node, reporting it from the rule analyzers would repeat it for every symbol or argument, and MA0104 is disabled by default so its analyzer may never run. The action walks the syntax trees of the compilation (the options can differ per tree) and reports each distinct invalid (key, value) once. The keys come from the existing ConfigurationDefinition fields, now internal instead of private, so there is no second list of key names to keep in sync.

Notes for the reviewer

  • The diagnostic has no location, as .editorconfig is not part of the compilation. It shows as a project level warning, and it can be configured through NoWarn or a global AnalyzerConfig (which is what the packaged configuration/*.editorconfig files are), but not through a [*.cs] section.
  • Severity is Warning, enabled by default. The issue suggested an informational diagnostic, but the closest precedent in the repository, MA0125 (LoggerParameterType_InvalidType), is a default-on warning, and an Info diagnostic without a location is nearly invisible in a normal build. Happy to switch it to Info.
  • The rule is regex specific. If one rule for any invalid option value is preferable, so future validations reuse it, only the title and the message need rewording: the RegexConfigurations array is already the extension point.
  • The existing Int32_ExcludedMethod_ShouldNotReportDiagnostic test was passing vacuously (its source reported nothing under the default expression_kinds, so the exclusion regex was never exercised); it now sets MA0003.expression_kinds = numeric.

Validation

  • The three tests of the fix fail on the code before it and pass after it.
  • dotnet run --project src/DocumentationGenerator reports no further change.
  • dotnet build: 0 warnings. dotnet test: 18754 tests pass on Roslyn 4.8, 4.14, 5.0, 5.6 and 5.9.

- RegexCache validates the pattern once and caches the failure, so an
  invalid value in the .editorconfig no longer throws (AD0001)
- The regexes use a finite timeout instead of Timeout.InfiniteTimeSpan
- MA0104 falls back to its default pattern, MA0003 excludes no method
- New rule MA0218 reports the invalid values
@meziantou
meziantou merged commit 60df5ba into main Aug 26, 2026
13 checks passed
@meziantou
meziantou deleted the feature/meziantou-analyzer-1329-c3e6da branch August 26, 2026 19:14
This was referenced Aug 26, 2026
This was referenced Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

A malformed regex in .editorconfig crashes MA0104/MA0003 (AD0001); both build regexes with an infinite timeout

1 participant