Created
October 19, 2023 21:45
-
-
Save tebeco/cf13f3fa8e3a1071a15a46db646f8cea to your computer and use it in GitHub Desktop.
AttrocityDetector
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Data.Common; | |
using System.Reflection.Metadata; | |
using Microsoft.Build.Locator; | |
using Microsoft.CodeAnalysis; | |
using Microsoft.CodeAnalysis.CSharp; | |
using Microsoft.CodeAnalysis.CSharp.Syntax; | |
using Microsoft.CodeAnalysis.MSBuild; | |
MSBuildLocator.RegisterDefaults(); | |
using var workspace = MSBuildWorkspace.Create(); | |
var solution = await workspace.OpenSolutionAsync(args[0]); | |
var apiProject = solution.Projects.Single(project => project.Name == args[1]); | |
var compilation = await apiProject.GetCompilationAsync(); | |
ArgumentNullException.ThrowIfNull(compilation); | |
var baseControllerSymbol = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Mvc.ControllerBase"); | |
var httpGetSymbol = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Mvc.HttpGetAttribute"); | |
var httpPostSymbol = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Mvc.HttpPostAttribute"); | |
var httpPutSymbol = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Mvc.HttpPutAttribute"); | |
var httpDeleteSymbol = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Mvc.HttpDeleteAttribute"); | |
var assemblyReference = compilation.References | |
.OfType<MetadataReference>() | |
.First(reference => reference.Display == args[2]); | |
var bannedAssemblySymbol = compilation.GetAssemblyOrModuleSymbol(assemblyReference); | |
var controllerFiles = compilation.SyntaxTrees.Where(tree => tree.FilePath.Contains("Controller.cs")); | |
var parameterSymbols = new List<(IMethodSymbol, IParameterSymbol)>(); | |
foreach (var controllerFile in controllerFiles) | |
{ | |
var semanticModel = compilation.GetSemanticModel(controllerFile); | |
var fileRoot = await controllerFile.GetRootAsync(); | |
var classDeclarations = fileRoot.DescendantNodes().OfType<ClassDeclarationSyntax>(); | |
foreach (var classDeclaration in classDeclarations) | |
{ | |
var classSymbol = semanticModel.GetDeclaredSymbol(classDeclaration) as ITypeSymbol; | |
if (classSymbol?.BaseType?.Equals(baseControllerSymbol, SymbolEqualityComparer.Default) == true) | |
{ | |
var endpoints = classSymbol | |
.GetMembers() | |
.OfType<IMethodSymbol>() | |
.Where(member => | |
member.DeclaredAccessibility == Accessibility.Public | |
&& member.GetAttributes().Any(attribute => | |
attribute.AttributeClass?.Equals(httpGetSymbol, SymbolEqualityComparer.Default) == true | |
|| attribute.AttributeClass?.Equals(httpPostSymbol, SymbolEqualityComparer.Default) == true | |
|| attribute.AttributeClass?.Equals(httpPutSymbol, SymbolEqualityComparer.Default) == true | |
|| attribute.AttributeClass?.Equals(httpDeleteSymbol, SymbolEqualityComparer.Default) == true)) | |
.Where(endpoint => endpoint.Parameters.Any()) | |
.SelectMany(endpoint => endpoint.Parameters.Select(parameter => (endpoint, parameter))) | |
; | |
foreach (var result in endpoints) | |
{ | |
var (method, parameter) = result; | |
Console.WriteLine(method.ContainingType.Name); | |
Console.WriteLine($"\t {method.Name}:"); | |
if (parameter.Type.ContainingAssembly.Equals(bannedAssemblySymbol, SymbolEqualityComparer.Default)) | |
{ | |
Console.ForegroundColor = ConsoleColor.Red; | |
} | |
Console.WriteLine($"\t\t {parameter.Type.Name} {parameter.Name} - {parameter.Type.ContainingAssembly.Name}"); | |
Console.ForegroundColor = ConsoleColor.Gray; | |
}; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment