Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit f0aa3ab

Browse files
authored
Use invariant culture when formatting transfer capture in regex source generator (#113081)
A balancing group can result in TransferCapture being emitted with a negative "capnum". If the compiler is running under a culture that uses something other than '-' as the negative sign, the resulting generated code will fail to compile.
1 parent 9d16e26 commit f0aa3ab

File tree

2 files changed

+24
-7
lines changed

2 files changed

+24
-7
lines changed

src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2573,7 +2573,7 @@ void EmitCapture(RegexNode node, RegexNode? subsequent = null)
25732573
}
25742574

25752575
writer.WriteLine();
2576-
writer.WriteLine($"base.TransferCapture({capnum}, {uncapnum}, {startingPos}, pos);");
2576+
writer.WriteLine($"base.TransferCapture({capnum.ToString(CultureInfo.InvariantCulture)}, {uncapnum}, {startingPos}, pos);");
25772577
}
25782578

25792579
if (isAtomic || !childBacktracks)

src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexGeneratorHelper.netcoreapp.cs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,12 @@ internal static async Task<Regex> SourceGenRegexAsync(
134134
return results[0];
135135
}
136136

137+
private static readonly CultureInfo s_cultureWithMinusNegativeSign = new CultureInfo("")
138+
{
139+
// To validate that generation still succeeds even when something other than '-' is used.
140+
NumberFormat = new NumberFormatInfo() { NegativeSign = $"{(char)0x2212}" }
141+
};
142+
137143
internal static async Task<Regex[]> SourceGenRegexAsync(
138144
(string pattern, CultureInfo? culture, RegexOptions? options, TimeSpan? matchTimeout)[] regexes, CancellationToken cancellationToken = default)
139145
{
@@ -214,13 +220,24 @@ internal static async Task<Regex[]> SourceGenRegexAsync(
214220
comp = comp.ReplaceSyntaxTree(comp.SyntaxTrees.First(), CSharpSyntaxTree.ParseText(SourceText.From(code.ToString(), Encoding.UTF8), s_previewParseOptions));
215221

216222
// Run the generator
217-
GeneratorDriverRunResult generatorResults = s_generatorDriver.RunGenerators(comp!, cancellationToken).GetRunResult();
218-
ImmutableArray<Diagnostic> generatorDiagnostics = generatorResults.Diagnostics.RemoveAll(d => d.Severity <= DiagnosticSeverity.Hidden);
219-
if (generatorDiagnostics.Length != 0)
223+
CultureInfo origCulture = CultureInfo.CurrentCulture;
224+
CultureInfo.CurrentCulture = s_cultureWithMinusNegativeSign;
225+
GeneratorDriverRunResult generatorResults;
226+
ImmutableArray<Diagnostic> generatorDiagnostics;
227+
try
220228
{
221-
throw new ArgumentException(
222-
string.Join(Environment.NewLine, generatorResults.GeneratedTrees.Select(t => NumberLines(t.ToString()))) + Environment.NewLine +
223-
string.Join(Environment.NewLine, generatorDiagnostics));
229+
generatorResults = s_generatorDriver.RunGenerators(comp!, cancellationToken).GetRunResult();
230+
generatorDiagnostics = generatorResults.Diagnostics.RemoveAll(d => d.Severity <= DiagnosticSeverity.Hidden);
231+
if (generatorDiagnostics.Length != 0)
232+
{
233+
throw new ArgumentException(
234+
string.Join(Environment.NewLine, generatorResults.GeneratedTrees.Select(t => NumberLines(t.ToString()))) + Environment.NewLine +
235+
string.Join(Environment.NewLine, generatorDiagnostics));
236+
}
237+
}
238+
finally
239+
{
240+
CultureInfo.CurrentCulture = origCulture;
224241
}
225242

226243
// Compile the assembly to a stream

0 commit comments

Comments
 (0)