Skip to content

Commit d2e5063

Browse files
committed
centralize regex patterns and add timeout
unifies regex definitions into a central descriptor list. adds a default timeout to regex construction for safety.
1 parent 5f7738f commit d2e5063

File tree

1 file changed

+60
-58
lines changed

1 file changed

+60
-58
lines changed

src/GitVersion.Core/Core/RegexPatterns.cs

Lines changed: 60 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace GitVersion.Core;
88
internal static partial class RegexPatterns
99
{
1010
private const RegexOptions Options = RegexOptions.IgnoreCase | RegexOptions.Compiled;
11+
private static readonly TimeSpan DefaultTimeout = TimeSpan.FromSeconds(2); // unified timeout for non-GeneratedRegex fallbacks
1112

1213
public static class Cache
1314
{
@@ -20,61 +21,67 @@ public static Regex GetOrAdd([StringSyntax(StringSyntaxAttribute.Regex)] string
2021
return cache.GetOrAdd(pattern, key =>
2122
KnownRegexes.TryGetValue(key, out var regex)
2223
? regex
23-
: new Regex(key, Options));
24+
: new Regex(key, Options, DefaultTimeout)); // now uses timeout for safety
2425
}
2526

27+
// Descriptor used to centralize pattern + compiled regex instance. Extendable with options/timeout metadata later.
28+
private readonly record struct RegexDescriptor(string Pattern, Regex Regex);
29+
30+
// Central descriptor list – single source of truth for known patterns. Order not significant.
31+
private static readonly RegexDescriptor[] Descriptors =
32+
[
33+
new(Common.SwitchArgumentRegexPattern, Common.SwitchArgumentRegex),
34+
new(Common.ObscurePasswordRegexPattern, Common.ObscurePasswordRegex),
35+
new(Common.ExpandTokensRegexPattern, Common.ExpandTokensRegex),
36+
new(Common.SanitizeEnvVarNameRegexPattern, Common.SanitizeEnvVarNameRegex),
37+
new(Common.SanitizeMemberNameRegexPattern, Common.SanitizeMemberNameRegex),
38+
new(Common.SanitizeNameRegexPattern, Common.SanitizeNameRegex),
39+
new(Configuration.DefaultTagPrefixRegexPattern, Configuration.DefaultTagPrefixRegex),
40+
new(Configuration.DefaultVersionInBranchRegexPattern, Configuration.DefaultVersionInBranchRegex),
41+
new(Configuration.MainBranchRegexPattern, Configuration.MainBranchRegex),
42+
new(Configuration.DevelopBranchRegexPattern, Configuration.DevelopBranchRegex),
43+
new(Configuration.ReleaseBranchRegexPattern, Configuration.ReleaseBranchRegex),
44+
new(Configuration.FeatureBranchRegexPattern, Configuration.FeatureBranchRegex),
45+
new(Configuration.PullRequestBranchRegexPattern, Configuration.PullRequestBranchRegex),
46+
new(Configuration.HotfixBranchRegexPattern, Configuration.HotfixBranchRegex),
47+
new(Configuration.SupportBranchRegexPattern, Configuration.SupportBranchRegex),
48+
new(Configuration.UnknownBranchRegexPattern, Configuration.UnknownBranchRegex),
49+
new(MergeMessage.DefaultMergeMessageRegexPattern, MergeMessage.DefaultMergeMessageRegex),
50+
new(MergeMessage.SmartGitMergeMessageRegexPattern, MergeMessage.SmartGitMergeMessageRegex),
51+
new(MergeMessage.BitBucketPullMergeMessageRegexPattern, MergeMessage.BitBucketPullMergeMessageRegex),
52+
new(MergeMessage.BitBucketPullv7MergeMessageRegexPattern, MergeMessage.BitBucketPullv7MergeMessageRegex),
53+
new(MergeMessage.BitBucketCloudPullMergeMessageRegexPattern, MergeMessage.BitBucketCloudPullMergeMessageRegex),
54+
new(MergeMessage.GitHubPullMergeMessageRegexPattern, MergeMessage.GitHubPullMergeMessageRegex),
55+
new(MergeMessage.RemoteTrackingMergeMessageRegexPattern, MergeMessage.RemoteTrackingMergeMessageRegex),
56+
new(MergeMessage.AzureDevOpsPullMergeMessageRegexPattern, MergeMessage.AzureDevOpsPullMergeMessageRegex),
57+
new(Output.AssemblyVersionRegexPattern, Output.AssemblyVersionRegex),
58+
new(Output.AssemblyInfoVersionRegexPattern, Output.AssemblyInfoVersionRegex),
59+
new(Output.AssemblyFileVersionRegexPattern, Output.AssemblyFileVersionRegex),
60+
new(Output.SanitizeAssemblyInfoRegexPattern, Output.SanitizeAssemblyInfoRegex),
61+
new(Output.CsharpAssemblyAttributeRegexPattern, Output.CsharpAssemblyAttributeRegex),
62+
new(Output.FsharpAssemblyAttributeRegexPattern, Output.FsharpAssemblyAttributeRegex),
63+
new(Output.VisualBasicAssemblyAttributeRegexPattern, Output.VisualBasicAssemblyAttributeRegex),
64+
new(Output.SanitizeParticipantRegexPattern, Output.SanitizeParticipantRegex),
65+
new(VersionCalculation.DefaultMajorRegexPattern, VersionCalculation.DefaultMajorRegex),
66+
new(VersionCalculation.DefaultMinorRegexPattern, VersionCalculation.DefaultMinorRegex),
67+
new(VersionCalculation.DefaultPatchRegexPattern, VersionCalculation.DefaultPatchRegex),
68+
new(VersionCalculation.DefaultNoBumpRegexPattern, VersionCalculation.DefaultNoBumpRegex),
69+
new(SemanticVersion.ParseStrictRegexPattern, SemanticVersion.ParseStrictRegex),
70+
new(SemanticVersion.ParseLooseRegexPattern, SemanticVersion.ParseLooseRegex),
71+
new(SemanticVersion.ParseBuildMetaDataRegexPattern, SemanticVersion.ParseBuildMetaDataRegex),
72+
new(SemanticVersion.FormatBuildMetaDataRegexPattern, SemanticVersion.FormatBuildMetaDataRegex),
73+
new(SemanticVersion.ParsePreReleaseTagRegexPattern, SemanticVersion.ParsePreReleaseTagRegex),
74+
// Trivia pattern unified: C# & F# share same underlying pattern; only map once under C# constant.
75+
new(AssemblyVersion.CSharp.TriviaRegexPattern, AssemblyVersion.CSharp.TriviaRegex),
76+
new(AssemblyVersion.CSharp.AttributeRegexPattern, AssemblyVersion.CSharp.AttributeRegex),
77+
// F# Trivia pattern identical – Attribute differs, so include attribute pattern only.
78+
new(AssemblyVersion.FSharp.AttributeRegexPattern, AssemblyVersion.FSharp.AttributeRegex),
79+
new(AssemblyVersion.VisualBasic.TriviaRegexPattern, AssemblyVersion.VisualBasic.TriviaRegex),
80+
new(AssemblyVersion.VisualBasic.AttributeRegexPattern, AssemblyVersion.VisualBasic.AttributeRegex)
81+
];
82+
2683
private static readonly ImmutableDictionary<string, Regex> KnownRegexes =
27-
new Dictionary<string, Regex>
28-
{
29-
[Common.SwitchArgumentRegexPattern] = Common.SwitchArgumentRegex,
30-
[Common.ObscurePasswordRegexPattern] = Common.ObscurePasswordRegex,
31-
[Common.ExpandTokensRegexPattern] = Common.ExpandTokensRegex,
32-
[Common.SanitizeEnvVarNameRegexPattern] = Common.SanitizeEnvVarNameRegex,
33-
[Common.SanitizeMemberNameRegexPattern] = Common.SanitizeMemberNameRegex,
34-
[Common.SanitizeNameRegexPattern] = Common.SanitizeNameRegex,
35-
[Configuration.DefaultTagPrefixRegexPattern] = Configuration.DefaultTagPrefixRegex,
36-
[Configuration.DefaultVersionInBranchRegexPattern] = Configuration.DefaultVersionInBranchRegex,
37-
[Configuration.MainBranchRegexPattern] = Configuration.MainBranchRegex,
38-
[Configuration.DevelopBranchRegexPattern] = Configuration.DevelopBranchRegex,
39-
[Configuration.ReleaseBranchRegexPattern] = Configuration.ReleaseBranchRegex,
40-
[Configuration.FeatureBranchRegexPattern] = Configuration.FeatureBranchRegex,
41-
[Configuration.PullRequestBranchRegexPattern] = Configuration.PullRequestBranchRegex,
42-
[Configuration.HotfixBranchRegexPattern] = Configuration.HotfixBranchRegex,
43-
[Configuration.SupportBranchRegexPattern] = Configuration.SupportBranchRegex,
44-
[Configuration.UnknownBranchRegexPattern] = Configuration.UnknownBranchRegex,
45-
[MergeMessage.DefaultMergeMessageRegexPattern] = MergeMessage.DefaultMergeMessageRegex,
46-
[MergeMessage.SmartGitMergeMessageRegexPattern] = MergeMessage.SmartGitMergeMessageRegex,
47-
[MergeMessage.BitBucketPullMergeMessageRegexPattern] = MergeMessage.BitBucketPullMergeMessageRegex,
48-
[MergeMessage.BitBucketPullv7MergeMessageRegexPattern] = MergeMessage.BitBucketPullv7MergeMessageRegex,
49-
[MergeMessage.BitBucketCloudPullMergeMessageRegexPattern] = MergeMessage.BitBucketCloudPullMergeMessageRegex,
50-
[MergeMessage.GitHubPullMergeMessageRegexPattern] = MergeMessage.GitHubPullMergeMessageRegex,
51-
[MergeMessage.RemoteTrackingMergeMessageRegexPattern] = MergeMessage.RemoteTrackingMergeMessageRegex,
52-
[MergeMessage.AzureDevOpsPullMergeMessageRegexPattern] = MergeMessage.AzureDevOpsPullMergeMessageRegex,
53-
[Output.AssemblyVersionRegexPattern] = Output.AssemblyVersionRegex,
54-
[Output.AssemblyInfoVersionRegexPattern] = Output.AssemblyInfoVersionRegex,
55-
[Output.AssemblyFileVersionRegexPattern] = Output.AssemblyFileVersionRegex,
56-
[Output.SanitizeAssemblyInfoRegexPattern] = Output.SanitizeAssemblyInfoRegex,
57-
[Output.CsharpAssemblyAttributeRegexPattern] = Output.CsharpAssemblyAttributeRegex,
58-
[Output.FsharpAssemblyAttributeRegexPattern] = Output.FsharpAssemblyAttributeRegex,
59-
[Output.VisualBasicAssemblyAttributeRegexPattern] = Output.VisualBasicAssemblyAttributeRegex,
60-
[Output.SanitizeParticipantRegexPattern] = Output.SanitizeParticipantRegex,
61-
[VersionCalculation.DefaultMajorRegexPattern] = VersionCalculation.DefaultMajorRegex,
62-
[VersionCalculation.DefaultMinorRegexPattern] = VersionCalculation.DefaultMinorRegex,
63-
[VersionCalculation.DefaultPatchRegexPattern] = VersionCalculation.DefaultPatchRegex,
64-
[VersionCalculation.DefaultNoBumpRegexPattern] = VersionCalculation.DefaultNoBumpRegex,
65-
[SemanticVersion.ParseStrictRegexPattern] = SemanticVersion.ParseStrictRegex,
66-
[SemanticVersion.ParseLooseRegexPattern] = SemanticVersion.ParseLooseRegex,
67-
[SemanticVersion.ParseBuildMetaDataRegexPattern] = SemanticVersion.ParseBuildMetaDataRegex,
68-
[SemanticVersion.FormatBuildMetaDataRegexPattern] = SemanticVersion.FormatBuildMetaDataRegex,
69-
[SemanticVersion.ParsePreReleaseTagRegexPattern] = SemanticVersion.ParsePreReleaseTagRegex,
70-
[AssemblyVersion.CSharp.TriviaRegexPattern] = AssemblyVersion.CSharp.TriviaRegex,
71-
[AssemblyVersion.CSharp.AttributeRegexPattern] = AssemblyVersion.CSharp.AttributeRegex,
72-
[AssemblyVersion.FSharp.TriviaRegexPattern] = AssemblyVersion.FSharp.TriviaRegex,
73-
// AssemblyVersion.FSharp.TriviaRegexPattern is same as C# so can't be added to the cache so C# TriviaRegex is used for F# as well.
74-
[AssemblyVersion.FSharp.AttributeRegexPattern] = AssemblyVersion.FSharp.AttributeRegex,
75-
[AssemblyVersion.VisualBasic.TriviaRegexPattern] = AssemblyVersion.VisualBasic.TriviaRegex,
76-
[AssemblyVersion.VisualBasic.AttributeRegexPattern] = AssemblyVersion.VisualBasic.AttributeRegex
77-
}.ToImmutableDictionary();
84+
Descriptors.ToImmutableDictionary(d => d.Pattern, d => d.Regex);
7885
}
7986

8087
internal static partial class Common
@@ -700,12 +707,7 @@ internal static partial class CSharp
700707
internal static partial class FSharp
701708
{
702709
[StringSyntax(StringSyntaxAttribute.Regex)]
703-
internal const string TriviaRegexPattern =
704-
"""
705-
/\*(.*?)\*/ # Block comments: matches /* ... */
706-
|//(.*?)\r?\n # Line comments: matches // ... followed by a newline
707-
|"((\\[^\n]|[^"\n])*)" # Strings: matches " ... " including escaped quotes
708-
""";
710+
internal const string TriviaRegexPattern = CSharp.TriviaRegexPattern; // unified
709711

710712
[StringSyntax(StringSyntaxAttribute.Regex)]
711713
internal const string AttributeRegexPattern =

0 commit comments

Comments
 (0)