From 6a406b28d1b8f2e27bfa8cb0d8850a62ffbc591c Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 14 Jan 2025 15:57:21 +0100 Subject: [PATCH] C#: Do not insert a synthetic ToString call in interpolation expressions, if the type implements IFormattable. --- .../CodeAnalysisExtensions/SymbolExtensions.cs | 6 ++++++ .../Entities/Expressions/InterpolatedString.cs | 11 ++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs index bb61efe332c8..cb1f36f8a2de 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/CodeAnalysisExtensions/SymbolExtensions.cs @@ -532,6 +532,12 @@ attribute.AttributeClass is INamedTypeSymbol nt && return isInline; } + /// + /// Returns true if this type implements `System.IFormattable`. + /// + public static bool ImplementsIFormattable(this ITypeSymbol type) => + type.AllInterfaces.Any(i => i.Name == "IFormattable" && i.ContainingNamespace.ToString() == "System"); + /// /// Holds if this type is of the form System.ReadOnlySpan<byte>. /// diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs index bdf30bf6618f..6d17d1e7f176 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs @@ -1,4 +1,5 @@ using System.IO; +using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Semmle.Extraction.Kinds; @@ -20,7 +21,15 @@ protected override void PopulateExpression(TextWriter trapFile) { case SyntaxKind.Interpolation: var interpolation = (InterpolationSyntax)c; - ImplicitToString.Create(Context, interpolation.Expression, this, child++); + var exp = interpolation.Expression; + if (Context.GetTypeInfo(exp).Type is ITypeSymbol type && !type.ImplementsIFormattable()) + { + ImplicitToString.Create(Context, exp, this, child++); + } + else + { + Create(Context, exp, this, child++); + } break; case SyntaxKind.InterpolatedStringText: // Create a string literal