Skip to content

Commit 3c00e9b

Browse files
committed
chore: Throw diagnostic errors for invalid parameter attribute names
1 parent 47856de commit 3c00e9b

File tree

6 files changed

+116
-0
lines changed

6 files changed

+116
-0
lines changed

Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/AnalyzerReleases.Shipped.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
; Shipped analyzer releases
22
; https://github.com/dotnet/roslyn-analyzers/blob/master/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md
33

4+
## Release 0.13.6.0
5+
Rule ID | Category | Severity | Notes
6+
--------|----------|----------|-------
7+
AWSLambda0110 | AWSLambdaCSharpGenerator | Error | Invalid Parameter Attribute Name
8+
49
## Release 0.13.4.0
510
Rule ID | Category | Severity | Notes
611
--------|----------|----------|-------

Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Diagnostics/DiagnosticDescriptors.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,12 @@ public static class DiagnosticDescriptors
8080
category: "AWSLambdaCSharpGenerator",
8181
DiagnosticSeverity.Error,
8282
isEnabledByDefault: true);
83+
84+
public static readonly DiagnosticDescriptor InvalidParameterAttributeName = new DiagnosticDescriptor(id: "AWSLambda0110",
85+
title: "Invalid Parameter Attribute Name",
86+
messageFormat: "Invalid parameter attribute name '{0}' for method parameter '{1}' encountered. Valid values can only contain uppercase and lowercase alphanumeric characters, periods (.), hyphens (-), underscores (_) and dollar signs ($).",
87+
category: "AWSLambdaCSharpGenerator",
88+
DiagnosticSeverity.Error,
89+
isEnabledByDefault: true);
8390
}
8491
}

Libraries/src/Amazon.Lambda.Annotations.SourceGenerator/Generator.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public class Generator : ISourceGenerator
2424
// Only allow alphanumeric characters
2525
private readonly Regex _resourceNameRegex = new Regex("^[a-zA-Z0-9]+$");
2626

27+
// Regex for the 'Name' property for API Gateway attributes - https://docs.aws.amazon.com/apigateway/latest/developerguide/request-response-data-mappings.html
28+
private readonly Regex _parameterAttributeNameRegex = new Regex("^[a-zA-Z0-9._$-]+$");
29+
2730
public Generator()
2831
{
2932
#if DEBUG
@@ -239,6 +242,39 @@ private bool AreLambdaMethodParamatersValid(MethodDeclarationSyntax declarationS
239242
parameterKey, parameter.Type.FullName));
240243
}
241244
}
245+
246+
foreach (var att in parameter.Attributes)
247+
{
248+
var parameterAttributeName = string.Empty;
249+
switch (att.Type.FullName)
250+
{
251+
case TypeFullNames.FromQueryAttribute:
252+
var fromQueryAttribute = (AttributeModel<APIGateway.FromQueryAttribute>)att;
253+
parameterAttributeName = fromQueryAttribute.Data.Name;
254+
break;
255+
256+
case TypeFullNames.FromRouteAttribute:
257+
var fromRouteAttribute = (AttributeModel<APIGateway.FromRouteAttribute>)att;
258+
parameterAttributeName = fromRouteAttribute.Data.Name;
259+
break;
260+
261+
case TypeFullNames.FromHeaderAttribute:
262+
var fromHeaderAttribute = (AttributeModel<APIGateway.FromHeaderAttribute>)att;
263+
parameterAttributeName = fromHeaderAttribute.Data.Name;
264+
break;
265+
266+
default:
267+
break;
268+
}
269+
270+
if (!string.IsNullOrEmpty(parameterAttributeName) && !_parameterAttributeNameRegex.IsMatch(parameterAttributeName))
271+
{
272+
isValid = false;
273+
diagnosticReporter.Report(Diagnostic.Create(DiagnosticDescriptors.InvalidParameterAttributeName,
274+
Location.Create(declarationSyntax.SyntaxTree, declarationSyntax.Span),
275+
parameterAttributeName, parameter.Name));
276+
}
277+
}
242278
}
243279

244280
return isValid;

Libraries/test/Amazon.Lambda.Annotations.SourceGenerators.Tests/SourceGeneratorTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -686,6 +686,40 @@ public async Task ComplexQueryParameters_AreNotSupported()
686686
}.RunAsync();
687687
}
688688

689+
[Fact]
690+
public async Task InvalidParameterAttributeNames_ThrowsDiagnosticErrors()
691+
{
692+
await new VerifyCS.Test
693+
{
694+
TestState =
695+
{
696+
Sources =
697+
{
698+
(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "PlaceholderClass.cs"))),
699+
(Path.Combine("TestServerlessApp", "InvalidParameterAttributeNames.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "InvalidParameterAttributeNames.cs.error"))),
700+
(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaFunctionAttribute.cs"))),
701+
(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "LambdaStartupAttribute.cs"))),
702+
(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "RestApiAttribute.cs"))),
703+
(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"), File.ReadAllText(Path.Combine("Amazon.Lambda.Annotations", "APIGateway", "HttpApiAttribute.cs"))),
704+
(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"), File.ReadAllText(Path.Combine("TestServerlessApp", "AssemblyAttributes.cs"))),
705+
},
706+
ExpectedDiagnostics =
707+
{
708+
DiagnosticResult.CompilerError("AWSLambda0110").WithSpan($"TestServerlessApp{Path.DirectorySeparatorChar}InvalidParameterAttributeNames.cs", 10, 9, 15, 10)
709+
.WithMessage("Invalid parameter attribute name 'This is a name' for method parameter 'name' encountered. Valid values can only contain uppercase and lowercase alphanumeric characters, periods (.), hyphens (-), underscores (_) and dollar signs ($)."),
710+
711+
DiagnosticResult.CompilerError("AWSLambda0110").WithSpan($"TestServerlessApp{Path.DirectorySeparatorChar}InvalidParameterAttributeNames.cs", 18, 9, 23, 10)
712+
.WithMessage("Invalid parameter attribute name 'System.Diagnostics.Process.Start(\"CMD.exe\",\"whoami\");' for method parameter 'test' encountered. Valid values can only contain uppercase and lowercase alphanumeric characters, periods (.), hyphens (-), underscores (_) and dollar signs ($)."),
713+
714+
DiagnosticResult.CompilerError("AWSLambda0110").WithSpan($"TestServerlessApp{Path.DirectorySeparatorChar}InvalidParameterAttributeNames.cs", 26, 9, 31, 10)
715+
.WithMessage("Invalid parameter attribute name 'first@name' for method parameter 'firstName' encountered. Valid values can only contain uppercase and lowercase alphanumeric characters, periods (.), hyphens (-), underscores (_) and dollar signs ($).")
716+
},
717+
ReferenceAssemblies = ReferenceAssemblies.Net.Net60
718+
}
719+
720+
}.RunAsync();
721+
}
722+
689723
public void Dispose()
690724
{
691725
File.Delete(Path.Combine("TestServerlessApp", "serverless.template"));
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
using Amazon.Lambda.Annotations;
2+
using Amazon.Lambda.Annotations.APIGateway;
3+
using Amazon.Lambda.Core;
4+
5+
namespace TestServerlessApp
6+
{
7+
public class InvalidParameterAttributeNames
8+
{
9+
// This fails because the FromQuery attribute name contains whitespaces
10+
[LambdaFunction()]
11+
[HttpApi(LambdaHttpMethod.Get, "/SayHello", Version = HttpApiVersion.V1)]
12+
public string SayHello([FromQuery(Name = "This is a name")] string name, ILambdaContext context)
13+
{
14+
return $"Hello, {name}!";
15+
}
16+
17+
// This fails because the FromHeader attribute name contains escape characters and ';'
18+
[LambdaFunction()]
19+
[HttpApi(LambdaHttpMethod.Get, "/inject")]
20+
public int Injection([FromHeader(Name = "System.Diagnostics.Process.Start(\"CMD.exe\",\"whoami\");")] int test, ILambdaContext context)
21+
{
22+
return 1;
23+
}
24+
25+
// This fails because the FromRoute attribute name contains '@'
26+
[LambdaFunction()]
27+
[HttpApi(LambdaHttpMethod.Get, "/SayHello/{first@name}", Version = HttpApiVersion.V1)]
28+
public string SayHelloFromRoute([FromRoute(Name = "first@name")] string firstName, ILambdaContext context)
29+
{
30+
return $"Hello, {firstName}!";
31+
}
32+
}
33+
}

Libraries/test/TestServerlessApp/TestServerlessApp.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<ItemGroup>
1616
<None Remove="ComplexQueryParameter.cs.error" />
1717
<None Remove="CustomizeResponseWithErrors.cs.error" />
18+
<None Remove="InvalidParameterAttributeNames.cs.error" />
1819
</ItemGroup>
1920
<ItemGroup>
2021
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />

0 commit comments

Comments
 (0)