Skip to content

Commit 944f0f5

Browse files
authored
Fix sanitization of type names in validations generator (#61952)
1 parent 302f094 commit 944f0f5

File tree

3 files changed

+44
-9
lines changed

3 files changed

+44
-9
lines changed

src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.ValidationsGenerator/Emitters/ValidationsGenerator.Emitter.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@
77
using System.Text;
88
using Microsoft.CodeAnalysis.CSharp;
99
using System.IO;
10+
using System.Text.RegularExpressions;
1011

1112
namespace Microsoft.AspNetCore.Http.ValidationsGenerator;
1213

1314
public sealed partial class ValidationsGenerator : IIncrementalGenerator
1415
{
1516
public static string GeneratedCodeConstructor => $@"global::System.CodeDom.Compiler.GeneratedCodeAttribute(""{typeof(ValidationsGenerator).Assembly.FullName}"", ""{typeof(ValidationsGenerator).Assembly.GetName().Version}"")";
1617
public static string GeneratedCodeAttribute => $"[{GeneratedCodeConstructor}]";
18+
private static readonly Regex InvalidNameCharsRegex = new("[^0-9A-Za-z_]", RegexOptions.Compiled);
1719

1820
internal static void Emit(SourceProductionContext context, (InterceptableLocation? AddValidation, ImmutableArray<ValidatableType> ValidatableTypes) emitInputs)
1921
{
@@ -238,12 +240,7 @@ private static void EmitValidatableMemberForCreate(ValidatableProperty member, C
238240

239241
private static string SanitizeTypeName(string typeName)
240242
{
241-
// Replace invalid characters with underscores and remove generic notation
242-
return typeName
243-
.Replace(".", "_")
244-
.Replace("<", "_")
245-
.Replace(">", "_")
246-
.Replace(",", "_")
247-
.Replace(" ", "_");
243+
// Replace invalid characters with underscores
244+
return InvalidNameCharsRegex.Replace(typeName, "_");
248245
}
249246
}

src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.Parameters.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public async Task CanValidateParameters()
2828
2929
var app = builder.Build();
3030
31-
app.MapGet("/params", (
31+
app.MapPost("/params", (
3232
// Skipped from validation because it is resolved as a service by IServiceProviderIsService
3333
TestService testService,
3434
// Skipped from validation because it is marked as a [FromKeyedService] parameter
@@ -39,7 +39,8 @@ public async Task CanValidateParameters()
3939
[CustomValidation(ErrorMessage = "Value must be an even number")] int value4 = 4,
4040
[CustomValidation, Range(10, 100)] int value5 = 10,
4141
// Skipped from validation because it is marked as a [FromService] parameter
42-
[FromServices] [Range(10, 100)] int? value6 = 4) => "OK");
42+
[FromServices] [Range(10, 100)] int? value6 = 4,
43+
Dictionary<string, TestService>? testDict = null) => "OK");
4344
4445
app.Run();
4546

src/Http/Http.Extensions/test/ValidationsGenerator/snapshots/ValidationsGeneratorTests.CanValidateParameters#ValidatableInfoResolver.g.verified.cs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ public bool TryGetValidatableTypeInfo(global::System.Type type, [global::System.
6767
validatableInfo = CreateTestService();
6868
return true;
6969
}
70+
if (type == typeof(global::System.Collections.Generic.Dictionary<string, global::TestService>))
71+
{
72+
validatableInfo = CreateDictionary_2();
73+
return true;
74+
}
7075

7176
return false;
7277
}
@@ -92,6 +97,38 @@ private ValidatableTypeInfo CreateTestService()
9297
]
9398
);
9499
}
100+
private ValidatableTypeInfo CreateDictionary_2()
101+
{
102+
return new GeneratedValidatableTypeInfo(
103+
type: typeof(global::System.Collections.Generic.Dictionary<string, global::TestService>),
104+
members: [
105+
new GeneratedValidatablePropertyInfo(
106+
containingType: typeof(global::System.Collections.Generic.Dictionary<string, global::TestService>),
107+
propertyType: typeof(global::System.Collections.Generic.ICollection<global::TestService>),
108+
name: "System.Collections.Generic.IDictionary<TKey,TValue>.Values",
109+
displayName: "System.Collections.Generic.IDictionary<TKey,TValue>.Values"
110+
),
111+
new GeneratedValidatablePropertyInfo(
112+
containingType: typeof(global::System.Collections.Generic.Dictionary<string, global::TestService>),
113+
propertyType: typeof(global::System.Collections.Generic.IEnumerable<global::TestService>),
114+
name: "System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>.Values",
115+
displayName: "System.Collections.Generic.IReadOnlyDictionary<TKey,TValue>.Values"
116+
),
117+
new GeneratedValidatablePropertyInfo(
118+
containingType: typeof(global::System.Collections.Generic.Dictionary<string, global::TestService>),
119+
propertyType: typeof(global::TestService),
120+
name: "this[]",
121+
displayName: "this[]"
122+
),
123+
new GeneratedValidatablePropertyInfo(
124+
containingType: typeof(global::System.Collections.Generic.Dictionary<string, global::TestService>),
125+
propertyType: typeof(global::System.Collections.ICollection),
126+
name: "System.Collections.IDictionary.Values",
127+
displayName: "System.Collections.IDictionary.Values"
128+
),
129+
]
130+
);
131+
}
95132

96133
}
97134

0 commit comments

Comments
 (0)