From e4e3ab3724f81a192196dba80615f56ee3fa872e Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Thu, 27 Mar 2025 13:27:33 -0700 Subject: [PATCH 1/2] Harden AddValidation check in validations generator --- .../ValidationsGenerator.AddValidation.cs | 7 +++ .../ValidationsGenerator.NoOp.cs | 56 +++++++++++++++++++ 2 files changed, 63 insertions(+) diff --git a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.ValidationsGenerator/Parsers/ValidationsGenerator.AddValidation.cs b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.ValidationsGenerator/Parsers/ValidationsGenerator.AddValidation.cs index fbf7673b19fd..1cb8061204ee 100644 --- a/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.ValidationsGenerator/Parsers/ValidationsGenerator.AddValidation.cs +++ b/src/Http/Http.Extensions/gen/Microsoft.AspNetCore.Http.ValidationsGenerator/Parsers/ValidationsGenerator.AddValidation.cs @@ -26,6 +26,13 @@ internal bool FindAddValidation(SyntaxNode syntaxNode, CancellationToken cancell { var node = (InvocationExpressionSyntax)context.Node; var semanticModel = context.SemanticModel; + var symbol = semanticModel.GetSymbolInfo(node, cancellationToken).Symbol; + if (symbol is not IMethodSymbol methodSymbol + || methodSymbol.ContainingType.Name != "ValidationServiceCollectionExtensions" + || methodSymbol.ContainingAssembly.Name != "Microsoft.AspNetCore.Http.Abstractions") + { + return null; + } return semanticModel.GetInterceptableLocation(node, cancellationToken); } } diff --git a/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs b/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs index 4249a7455bf0..b1a553c87f53 100644 --- a/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs +++ b/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs @@ -51,6 +51,62 @@ await VerifyEndpoint(compilation, "/complex-type", async (endpoint, serviceProvi }); } + [Fact] + public async Task DoesNotEmitIfNotCorrectAddValidationCallExists() + { + // Arrange + var source = """ +using System; +using System.ComponentModel.DataAnnotations; +using System.Collections.Generic; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Builder; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Routing; +using Microsoft.Extensions.DependencyInjection; + +var builder = WebApplication.CreateBuilder(); + +builder.Services.AddValidation("example"); + +var app = builder.Build(); + +app.MapPost("/complex-type", (ComplexType complexType) => Results.Ok("Passed")); + +app.Run(); + +public class ComplexType +{ + [Range(10, 100)] + public int IntegerWithRange { get; set; } = 10; +} + +public static class SomeExtensions +{ + public static IServiceCollection AddValidation(this IServiceCollection services, string someString) + { + // This is not the correct AddValidation method + return services; + } +} +"""; + await Verify(source, out var compilation); + // Verify that we don't validate types if no AddValidation call exists + await VerifyEndpoint(compilation, "/complex-type", async (endpoint, serviceProvider) => + { + var payload = """ + { + "IntegerWithRange": 5 + } + """; + var context = CreateHttpContextWithPayload(payload, serviceProvider); + + await endpoint.RequestDelegate(context); + + Assert.Equal(StatusCodes.Status200OK, context.Response.StatusCode); + }); + } + [Fact] public async Task DoesNotEmitForExemptTypes() { From a28f2384c741d219a354384481a214b72dfac302 Mon Sep 17 00:00:00 2001 From: Safia Abdalla Date: Thu, 27 Mar 2025 13:55:08 -0700 Subject: [PATCH 2/2] Add test case --- .../ValidationsGenerator/ValidationsGenerator.NoOp.cs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs b/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs index b1a553c87f53..410c74a5cecc 100644 --- a/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs +++ b/src/Http/Http.Extensions/test/ValidationsGenerator/ValidationsGenerator.NoOp.cs @@ -62,12 +62,14 @@ public async Task DoesNotEmitIfNotCorrectAddValidationCallExists() using System.Threading.Tasks; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Validation; using Microsoft.AspNetCore.Routing; using Microsoft.Extensions.DependencyInjection; var builder = WebApplication.CreateBuilder(); builder.Services.AddValidation("example"); +SomeExtensions.AddValidation(builder.Services); var app = builder.Build(); @@ -88,6 +90,12 @@ public static IServiceCollection AddValidation(this IServiceCollection services, // This is not the correct AddValidation method return services; } + + public static IServiceCollection AddValidation(this IServiceCollection services, Action? configureOptions = null) + { + // This is not the correct AddValidation method + return services; + } } """; await Verify(source, out var compilation);