From 261b8db144e844ef205c029fed40e21402d2c91a Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 8 Jan 2025 14:06:29 +0100 Subject: [PATCH 01/22] C#: Add some implicit toString data flow test cases. --- .../implicittostring/implicitToString.cs | 43 +++++++++++++++++++ .../implicitToString.expected | 20 +++++++++ .../implicittostring/implicitToString.ql | 19 ++++++++ 3 files changed, 82 insertions(+) create mode 100644 csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs create mode 100644 csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected create mode 100644 csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.ql diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs new file mode 100644 index 000000000000..0e1406e74ddb --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs @@ -0,0 +1,43 @@ +using System; + +public class TestClass +{ + public class MyClass() + { + public override string ToString() + { + return "tainted"; + } + } + + public static void Sink(object o) { } + + public void M1() + { + var x1 = new MyClass(); + var x2 = "Hello" + x1.ToString(); + Sink(x2); + } + + public void M2() + { + var x1 = new MyClass(); + var x2 = "Hello" + x1; + Sink(x2); // MISSING + } + + public void M3() + { + var x1 = new MyClass(); + var x2 = $"Hello {x1.ToString()}"; + Sink(x2); + } + + public void M4() + { + var x1 = new MyClass(); + var x2 = $"Hello {x1}"; + Sink(x2); // Missing + } + +} diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected new file mode 100644 index 000000000000..245c2f091f0d --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected @@ -0,0 +1,20 @@ +models +edges +| implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:18:28:18:40 | call to method ToString : String | provenance | | +| implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:32:27:32:39 | call to method ToString : String | provenance | | +| implicitToString.cs:18:13:18:14 | access to local variable x2 : String | implicitToString.cs:19:14:19:15 | access to local variable x2 | provenance | | +| implicitToString.cs:18:28:18:40 | call to method ToString : String | implicitToString.cs:18:13:18:14 | access to local variable x2 : String | provenance | | +| implicitToString.cs:32:13:32:14 | access to local variable x2 : String | implicitToString.cs:33:14:33:15 | access to local variable x2 | provenance | | +| implicitToString.cs:32:27:32:39 | call to method ToString : String | implicitToString.cs:32:13:32:14 | access to local variable x2 : String | provenance | | +nodes +| implicitToString.cs:9:20:9:28 | "tainted" : String | semmle.label | "tainted" : String | +| implicitToString.cs:18:13:18:14 | access to local variable x2 : String | semmle.label | access to local variable x2 : String | +| implicitToString.cs:18:28:18:40 | call to method ToString : String | semmle.label | call to method ToString : String | +| implicitToString.cs:19:14:19:15 | access to local variable x2 | semmle.label | access to local variable x2 | +| implicitToString.cs:32:13:32:14 | access to local variable x2 : String | semmle.label | access to local variable x2 : String | +| implicitToString.cs:32:27:32:39 | call to method ToString : String | semmle.label | call to method ToString : String | +| implicitToString.cs:33:14:33:15 | access to local variable x2 | semmle.label | access to local variable x2 | +subpaths +#select +| implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:19:14:19:15 | access to local variable x2 | $@ | implicitToString.cs:19:14:19:15 | access to local variable x2 | access to local variable x2 | +| implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:33:14:33:15 | access to local variable x2 | $@ | implicitToString.cs:33:14:33:15 | access to local variable x2 | access to local variable x2 | diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.ql b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.ql new file mode 100644 index 000000000000..85797414ee5d --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.ql @@ -0,0 +1,19 @@ +import csharp +import utils.test.ProvenancePathGraph::ShowProvenance + +module TtConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr().(StringLiteral).getValue() = "tainted" } + + predicate isSink(DataFlow::Node sink) { + exists(MethodCall mc | + mc.getTarget().hasUndecoratedName("Sink") and + mc.getAnArgument() = sink.asExpr() + ) + } +} + +module Tt = TaintTracking::Global; + +from Tt::PathNode source, Tt::PathNode sink +where Tt::flowPath(source, sink) +select source, source, sink, "$@", sink, sink.toString() From f905be4df34aa11f71b217d34409025fc4a3b946 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 9 Jan 2025 10:39:05 +0100 Subject: [PATCH 02/22] C#: Add a RedundantToStringCall test case. --- .../RedundantToStringCall/RedundantToStringCall.cs | 3 +++ .../RedundantToStringCall/RedundantToStringCall.expected | 1 + 2 files changed, 4 insertions(+) diff --git a/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.cs b/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.cs index 2f863966f351..981b36002663 100644 --- a/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.cs +++ b/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.cs @@ -9,5 +9,8 @@ public void M(object o) Console.WriteLine($"Hello: {o.ToString()}"); // BAD Console.WriteLine($"Hello: {o}"); // GOOD + + Console.WriteLine("Hello: " + o.ToString()); // BAD + Console.WriteLine("Hello: " + o); // GOOD } } diff --git a/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.expected b/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.expected index 8021c21df2ae..28775378f049 100644 --- a/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.expected +++ b/csharp/ql/test/query-tests/Useless Code/RedundantToStringCall/RedundantToStringCall.expected @@ -1,3 +1,4 @@ | RedundantToStringCall.cs:7:27:7:38 | call to method ToString | Redundant call to 'ToString' on a String object. | | RedundantToStringCall.cs:10:37:10:48 | call to method ToString | Redundant call to 'ToString' on a String object. | +| RedundantToStringCall.cs:13:39:13:50 | call to method ToString | Redundant call to 'ToString' on a String object. | | RedundantToStringCallBad.cs:7:45:7:56 | call to method ToString | Redundant call to 'ToString' on a String object. | From 908a3e35638d5ad2543bec92c115f429fb629c3f Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 8 Jan 2025 14:11:01 +0100 Subject: [PATCH 03/22] C#: Make synthetic ToString calls in binary add expressions. --- .../Entities/Expression.cs | 2 +- .../Entities/ExpressionNodeInfo.cs | 14 ++++- .../Entities/Expressions/Binary.cs | 28 ++++++++- .../Entities/Expressions/ImplicitCast.cs | 6 ++ .../Entities/Expressions/ImplicitToString.cs | 59 +++++++++++++++++++ 5 files changed, 105 insertions(+), 4 deletions(-) create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitToString.cs diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs index 9241528eb752..a5cb6e316f41 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expression.cs @@ -129,7 +129,7 @@ public static void CreateDeferred(Context cx, ExpressionSyntax node, IExpression cx.PopulateLater(() => Create(cx, node, parent, child)); } - private static bool ContainsPattern(SyntaxNode node) => + protected static bool ContainsPattern(SyntaxNode node) => node is PatternSyntax || node is VariableDesignationSyntax || node.ChildNodes().Any(ContainsPattern); /// diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs index 924382a55507..5a2cad8a520a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/ExpressionNodeInfo.cs @@ -129,7 +129,13 @@ public Location Location public ExprKind Kind { get; set; } = ExprKind.UNKNOWN; - public bool IsCompilerGenerated { get; set; } + public bool IsCompilerGenerated { get; init; } + + /// + /// Whether the expression should have a compiler generated `ToString` call added, + /// if there is no suitable implicit cast. + /// + public bool ImplicitToString { get; private set; } public ExpressionNodeInfo SetParent(IExpressionParentEntity parent, int child) { @@ -157,6 +163,12 @@ public ExpressionNodeInfo SetNode(ExpressionSyntax node) return this; } + public ExpressionNodeInfo SetImplicitToString(bool value) + { + ImplicitToString = value; + return this; + } + private SymbolInfo cachedSymbolInfo; public SymbolInfo SymbolInfo diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Binary.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Binary.cs index 3cdfb32277b2..eeb1b9ba63b2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Binary.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Binary.cs @@ -14,11 +14,35 @@ private Binary(ExpressionNodeInfo info) public static Expression Create(ExpressionNodeInfo info) => new Binary(info).TryPopulate(); + private Expression CreateChild(Context cx, ExpressionSyntax node, int child) + { + // If this is a "+" expression we might need to wrap the child expressions + // in ToString calls + return Kind == ExprKind.ADD + ? ImplicitToString.Create(cx, node, this, child) + : Create(cx, node, this, child); + } + + /// + /// Creates an expression from a syntax node. + /// Inserts type conversion as required. + /// Population is deferred to avoid overflowing the stack. + /// + private void CreateDeferred(Context cx, ExpressionSyntax node, int child) + { + if (ContainsPattern(node)) + // Expressions with patterns should be created right away, as they may introduce + // local variables referenced in `LocalVariable::GetAlreadyCreated()` + CreateChild(cx, node, child); + else + cx.PopulateLater(() => CreateChild(cx, node, child)); + } + protected override void PopulateExpression(TextWriter trapFile) { OperatorCall(trapFile, Syntax); - CreateDeferred(Context, Syntax.Left, this, 0); - CreateDeferred(Context, Syntax.Right, this, 1); + CreateDeferred(Context, Syntax.Left, 0); + CreateDeferred(Context, Syntax.Right, 1); } private static ExprKind GetKind(Context cx, BinaryExpressionSyntax node) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs index b0508bf83b7e..c1ce5dcbfe99 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitCast.cs @@ -156,6 +156,12 @@ convertedType.Symbol is IPointerTypeSymbol && return new ImplicitCast(info); } + if (info.ImplicitToString) + { + // x -> x.ToString() in "abc" + x + return ImplicitToString.Wrap(info); + } + // Default: Just create the expression without a conversion. return Factory.Create(info); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitToString.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitToString.cs new file mode 100644 index 000000000000..f424e98a7a51 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ImplicitToString.cs @@ -0,0 +1,59 @@ +using System.Linq; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.CSharp.Syntax; +using Semmle.Extraction.CSharp.Util; +using Semmle.Extraction.Kinds; + + +namespace Semmle.Extraction.CSharp.Entities.Expressions +{ + internal sealed class ImplicitToString : Expression + { + /// + /// Gets the `ToString` method for the given type. + /// + private static IMethodSymbol? GetToStringMethod(ITypeSymbol? type) + { + return type? + .GetMembers() + .OfType() + .Where(method => + method.GetName() == "ToString" && + method.Parameters.Length == 0 + ) + .FirstOrDefault(); + } + + private ImplicitToString(ExpressionNodeInfo info, IMethodSymbol toString) : base(new ExpressionInfo(info.Context, AnnotatedTypeSymbol.CreateNotAnnotated(toString.ReturnType), info.Location, ExprKind.METHOD_INVOCATION, info.Parent, info.Child, isCompilerGenerated: true, info.ExprValue)) + { + Factory.Create(info.SetParent(this, -1)); + + var target = Method.Create(Context, toString); + Context.TrapWriter.Writer.expr_call(this, target); + } + + private static bool IsStringType(AnnotatedTypeSymbol? type) => + type.HasValue && type.Value.Symbol?.SpecialType == SpecialType.System_String; + + /// + /// Creates a new expression, adding a compiler generated `ToString` call if required. + /// + public static Expression Create(Context cx, ExpressionSyntax node, Expression parent, int child) + { + var info = new ExpressionNodeInfo(cx, node, parent, child); + return CreateFromNode(info.SetImplicitToString(IsStringType(parent.Type) && !IsStringType(info.Type))); + } + + /// + /// Wraps the resulting expression in a `ToString` call, if a suitable `ToString` method is available. + /// + public static Expression Wrap(ExpressionNodeInfo info) + { + if (GetToStringMethod(info.Type?.Symbol) is IMethodSymbol toString) + { + return new ImplicitToString(info, toString); + } + return Factory.Create(info); + } + } +} From e9beeac60f96bc6604dac586846bbf0a1cc4555e Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 8 Jan 2025 14:15:05 +0100 Subject: [PATCH 04/22] C#: Update test expected output. --- .../dataflow/implicittostring/implicitToString.cs | 2 +- .../dataflow/implicittostring/implicitToString.expected | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs index 0e1406e74ddb..132100bf38a0 100644 --- a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs +++ b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs @@ -23,7 +23,7 @@ public void M2() { var x1 = new MyClass(); var x2 = "Hello" + x1; - Sink(x2); // MISSING + Sink(x2); } public void M3() diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected index 245c2f091f0d..448e08b48452 100644 --- a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected +++ b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected @@ -1,9 +1,12 @@ models edges | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:18:28:18:40 | call to method ToString : String | provenance | | +| implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:25:28:25:29 | call to method ToString : String | provenance | | | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:32:27:32:39 | call to method ToString : String | provenance | | | implicitToString.cs:18:13:18:14 | access to local variable x2 : String | implicitToString.cs:19:14:19:15 | access to local variable x2 | provenance | | | implicitToString.cs:18:28:18:40 | call to method ToString : String | implicitToString.cs:18:13:18:14 | access to local variable x2 : String | provenance | | +| implicitToString.cs:25:13:25:14 | access to local variable x2 : String | implicitToString.cs:26:14:26:15 | access to local variable x2 | provenance | | +| implicitToString.cs:25:28:25:29 | call to method ToString : String | implicitToString.cs:25:13:25:14 | access to local variable x2 : String | provenance | | | implicitToString.cs:32:13:32:14 | access to local variable x2 : String | implicitToString.cs:33:14:33:15 | access to local variable x2 | provenance | | | implicitToString.cs:32:27:32:39 | call to method ToString : String | implicitToString.cs:32:13:32:14 | access to local variable x2 : String | provenance | | nodes @@ -11,10 +14,14 @@ nodes | implicitToString.cs:18:13:18:14 | access to local variable x2 : String | semmle.label | access to local variable x2 : String | | implicitToString.cs:18:28:18:40 | call to method ToString : String | semmle.label | call to method ToString : String | | implicitToString.cs:19:14:19:15 | access to local variable x2 | semmle.label | access to local variable x2 | +| implicitToString.cs:25:13:25:14 | access to local variable x2 : String | semmle.label | access to local variable x2 : String | +| implicitToString.cs:25:28:25:29 | call to method ToString : String | semmle.label | call to method ToString : String | +| implicitToString.cs:26:14:26:15 | access to local variable x2 | semmle.label | access to local variable x2 | | implicitToString.cs:32:13:32:14 | access to local variable x2 : String | semmle.label | access to local variable x2 : String | | implicitToString.cs:32:27:32:39 | call to method ToString : String | semmle.label | call to method ToString : String | | implicitToString.cs:33:14:33:15 | access to local variable x2 | semmle.label | access to local variable x2 | subpaths #select | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:19:14:19:15 | access to local variable x2 | $@ | implicitToString.cs:19:14:19:15 | access to local variable x2 | access to local variable x2 | +| implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:26:14:26:15 | access to local variable x2 | $@ | implicitToString.cs:26:14:26:15 | access to local variable x2 | access to local variable x2 | | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:33:14:33:15 | access to local variable x2 | $@ | implicitToString.cs:33:14:33:15 | access to local variable x2 | access to local variable x2 | From 5f539c5515eda5e57400006a74736d6d10d722df Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Fri, 10 Jan 2025 12:53:24 +0100 Subject: [PATCH 05/22] C#: Make synthetic ToString calls in string interpolation expressions. --- .../Entities/Expressions/InterpolatedString.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs index 2dfe4976391d..bdf30bf6618f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/InterpolatedString.cs @@ -20,7 +20,7 @@ protected override void PopulateExpression(TextWriter trapFile) { case SyntaxKind.Interpolation: var interpolation = (InterpolationSyntax)c; - Create(Context, interpolation.Expression, this, child++); + ImplicitToString.Create(Context, interpolation.Expression, this, child++); break; case SyntaxKind.InterpolatedStringText: // Create a string literal From 8bf67e37fe3e8a44b93a56a66045cdaeb59b2726 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Fri, 10 Jan 2025 12:56:35 +0100 Subject: [PATCH 06/22] C#: Update test expected output. --- .../dataflow/implicittostring/implicitToString.cs | 2 +- .../dataflow/implicittostring/implicitToString.expected | 7 +++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs index 132100bf38a0..84c8737204d8 100644 --- a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs +++ b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.cs @@ -37,7 +37,7 @@ public void M4() { var x1 = new MyClass(); var x2 = $"Hello {x1}"; - Sink(x2); // Missing + Sink(x2); } } diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected index 448e08b48452..aa77f131e890 100644 --- a/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected +++ b/csharp/ql/test/library-tests/dataflow/implicittostring/implicitToString.expected @@ -3,12 +3,15 @@ edges | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:18:28:18:40 | call to method ToString : String | provenance | | | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:25:28:25:29 | call to method ToString : String | provenance | | | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:32:27:32:39 | call to method ToString : String | provenance | | +| implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:39:27:39:28 | call to method ToString : String | provenance | | | implicitToString.cs:18:13:18:14 | access to local variable x2 : String | implicitToString.cs:19:14:19:15 | access to local variable x2 | provenance | | | implicitToString.cs:18:28:18:40 | call to method ToString : String | implicitToString.cs:18:13:18:14 | access to local variable x2 : String | provenance | | | implicitToString.cs:25:13:25:14 | access to local variable x2 : String | implicitToString.cs:26:14:26:15 | access to local variable x2 | provenance | | | implicitToString.cs:25:28:25:29 | call to method ToString : String | implicitToString.cs:25:13:25:14 | access to local variable x2 : String | provenance | | | implicitToString.cs:32:13:32:14 | access to local variable x2 : String | implicitToString.cs:33:14:33:15 | access to local variable x2 | provenance | | | implicitToString.cs:32:27:32:39 | call to method ToString : String | implicitToString.cs:32:13:32:14 | access to local variable x2 : String | provenance | | +| implicitToString.cs:39:13:39:14 | access to local variable x2 : String | implicitToString.cs:40:14:40:15 | access to local variable x2 | provenance | | +| implicitToString.cs:39:27:39:28 | call to method ToString : String | implicitToString.cs:39:13:39:14 | access to local variable x2 : String | provenance | | nodes | implicitToString.cs:9:20:9:28 | "tainted" : String | semmle.label | "tainted" : String | | implicitToString.cs:18:13:18:14 | access to local variable x2 : String | semmle.label | access to local variable x2 : String | @@ -20,8 +23,12 @@ nodes | implicitToString.cs:32:13:32:14 | access to local variable x2 : String | semmle.label | access to local variable x2 : String | | implicitToString.cs:32:27:32:39 | call to method ToString : String | semmle.label | call to method ToString : String | | implicitToString.cs:33:14:33:15 | access to local variable x2 | semmle.label | access to local variable x2 | +| implicitToString.cs:39:13:39:14 | access to local variable x2 : String | semmle.label | access to local variable x2 : String | +| implicitToString.cs:39:27:39:28 | call to method ToString : String | semmle.label | call to method ToString : String | +| implicitToString.cs:40:14:40:15 | access to local variable x2 | semmle.label | access to local variable x2 | subpaths #select | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:19:14:19:15 | access to local variable x2 | $@ | implicitToString.cs:19:14:19:15 | access to local variable x2 | access to local variable x2 | | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:26:14:26:15 | access to local variable x2 | $@ | implicitToString.cs:26:14:26:15 | access to local variable x2 | access to local variable x2 | | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:33:14:33:15 | access to local variable x2 | $@ | implicitToString.cs:33:14:33:15 | access to local variable x2 | access to local variable x2 | +| implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:9:20:9:28 | "tainted" : String | implicitToString.cs:40:14:40:15 | access to local variable x2 | $@ | implicitToString.cs:40:14:40:15 | access to local variable x2 | access to local variable x2 | From a4049b1d9a7e46baa55db219e6fc80cff5d38945 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 9 Jan 2025 11:36:17 +0100 Subject: [PATCH 07/22] C#: Modify compiler generated strip logic to also take generated ToString calls into account. --- csharp/ql/examples/snippets/ternary_conditional.ql | 2 +- .../lib/semmle/code/csharp/commons/Constants.qll | 2 +- .../ql/lib/semmle/code/csharp/commons/Strings.qll | 6 +++--- .../lib/semmle/code/csharp/dispatch/Dispatch.qll | 2 +- csharp/ql/lib/semmle/code/csharp/exprs/Call.qll | 4 ++++ csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll | 14 +++++++++++--- .../ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql | 4 ++-- csharp/ql/src/Likely Bugs/ObjectComparison.ql | 2 +- 8 files changed, 24 insertions(+), 12 deletions(-) diff --git a/csharp/ql/examples/snippets/ternary_conditional.ql b/csharp/ql/examples/snippets/ternary_conditional.ql index 22e26e71ea8f..009c56fb2afe 100644 --- a/csharp/ql/examples/snippets/ternary_conditional.ql +++ b/csharp/ql/examples/snippets/ternary_conditional.ql @@ -11,7 +11,7 @@ import csharp from ConditionalExpr e where - e.getThen().stripImplicitCasts() != e.getElse().stripImplicitCasts() and + e.getThen().stripImplicit() != e.getElse().stripImplicit() and not e.getThen().getType() instanceof NullType and not e.getElse().getType() instanceof NullType select e diff --git a/csharp/ql/lib/semmle/code/csharp/commons/Constants.qll b/csharp/ql/lib/semmle/code/csharp/commons/Constants.qll index 1d6e67aa488d..508ba0e5e87d 100644 --- a/csharp/ql/lib/semmle/code/csharp/commons/Constants.qll +++ b/csharp/ql/lib/semmle/code/csharp/commons/Constants.qll @@ -43,7 +43,7 @@ predicate isConstantComparison(ComparisonOperation co, boolean b) { private module ConstantComparisonOperation { private import semmle.code.csharp.commons.ComparisonTest - private SimpleType convertedType(Expr expr) { result = expr.stripImplicitCasts().getType() } + private SimpleType convertedType(Expr expr) { result = expr.stripImplicit().getType() } private int maxValue(Expr expr) { if convertedType(expr) instanceof IntegralType and exists(expr.getValue()) diff --git a/csharp/ql/lib/semmle/code/csharp/commons/Strings.qll b/csharp/ql/lib/semmle/code/csharp/commons/Strings.qll index 4e007d61737e..908d1c2fb5ab 100644 --- a/csharp/ql/lib/semmle/code/csharp/commons/Strings.qll +++ b/csharp/ql/lib/semmle/code/csharp/commons/Strings.qll @@ -44,11 +44,11 @@ class ImplicitToStringExpr extends Expr { ) or exists(AddExpr add, Expr o | o = add.getAnOperand() | - o.stripImplicitCasts().getType() instanceof StringType and - this = add.getOtherOperand(o) + o.stripImplicit().getType() instanceof StringType and + this = add.getOtherOperand(o).stripImplicit() ) or - this = any(InterpolatedStringExpr ise).getAnInsert() + this = any(InterpolatedStringExpr ise).getAnInsert().stripImplicit() } } diff --git a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll index 080b7d5c7325..7de6c30eb13c 100644 --- a/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll +++ b/csharp/ql/lib/semmle/code/csharp/dispatch/Dispatch.qll @@ -857,7 +857,7 @@ private module Internal { private predicate hasDynamicArg(int i, Type argumentType) { exists(Expr argument | argument = this.getArgument(i) and - argument.stripImplicitCasts().getType() instanceof DynamicType and + argument.stripImplicit().getType() instanceof DynamicType and argumentType = getAPossibleType(argument, _) ) } diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll index be4577d760eb..eecbc35900aa 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Call.qll @@ -281,6 +281,10 @@ class MethodCall extends Call, QualifiableExpr, LateBindableExpr, @method_invoca result = this.getArgument(i - 1) else result = this.getArgument(i) } + + override Expr stripImplicit() { + if this.isImplicit() then result = this.getQualifier().stripImplicit() else result = this + } } /** diff --git a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll index 935162523a16..85676bbd2701 100644 --- a/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll +++ b/csharp/ql/lib/semmle/code/csharp/exprs/Expr.qll @@ -82,10 +82,18 @@ class Expr extends ControlFlowElement, @expr { Expr stripCasts() { result = this } /** + * DEPRECATED: Use `stripImplicit` instead. + * * Gets an expression that is the result of stripping (recursively) all * implicit casts from this expression, if any. */ - Expr stripImplicitCasts() { result = this } + deprecated Expr stripImplicitCasts() { result = this.stripImplicit() } + + /** + * Gets an expression that is the result of stripping (recursively) all + * implicit casts and implicit ToString calls from this expression, if any. + */ + Expr stripImplicit() { result = this } /** * Gets the explicit parameter name used to pass this expression as an @@ -714,8 +722,8 @@ class Cast extends Expr { override Expr stripCasts() { result = this.getExpr().stripCasts() } - override Expr stripImplicitCasts() { - if this.isImplicit() then result = this.getExpr().stripImplicitCasts() else result = this + override Expr stripImplicit() { + if this.isImplicit() then result = this.getExpr().stripImplicit() else result = this } } diff --git a/csharp/ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql b/csharp/ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql index 6044ebbbb5eb..2efac6773f72 100644 --- a/csharp/ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql +++ b/csharp/ql/src/Likely Bugs/Dynamic/BadDynamicCall.ql @@ -44,11 +44,11 @@ abstract class BadDynamicCall extends DynamicExpr { ultimateSsaDef = ssaDef.getAnUltimateDefinition() | ultimateSsaDef.getADefinition() = - any(AssignableDefinition def | source = def.getSource().stripImplicitCasts()) + any(AssignableDefinition def | source = def.getSource().stripImplicit()) or ultimateSsaDef.getADefinition() = any(AssignableDefinitions::ImplicitParameterDefinition p | - source = p.getParameter().getAnAssignedValue().stripImplicitCasts() + source = p.getParameter().getAnAssignedValue().stripImplicit() ) ) } diff --git a/csharp/ql/src/Likely Bugs/ObjectComparison.ql b/csharp/ql/src/Likely Bugs/ObjectComparison.ql index 53b525b6072c..eec1961fbf50 100644 --- a/csharp/ql/src/Likely Bugs/ObjectComparison.ql +++ b/csharp/ql/src/Likely Bugs/ObjectComparison.ql @@ -28,7 +28,7 @@ class ReferenceEqualityTestOnObject extends EqualityOperation { exists(getObjectOperand(this)) and // Neither operand is 'null'. not this.getAnOperand() instanceof NullLiteral and - not exists(Type t | t = this.getAnOperand().stripImplicitCasts().getType() | + not exists(Type t | t = this.getAnOperand().stripImplicit().getType() | t instanceof NullType or t instanceof ValueType ) and From 6c6e58b3373a7760fb1e209ad4b81cc07ce3eaa4 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 9 Jan 2025 13:50:10 +0100 Subject: [PATCH 08/22] C#: Add PrintAst test to implicit ToString test. --- .../implicittostring/PrintAst.expected | 93 +++++++++++++++++++ .../dataflow/implicittostring/PrintAst.qlref | 1 + 2 files changed, 94 insertions(+) create mode 100644 csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected create mode 100644 csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.qlref diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected b/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected new file mode 100644 index 000000000000..7b3215415230 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected @@ -0,0 +1,93 @@ +implicitToString.cs: +# 3| [Class] TestClass +# 5| 5: [Class] MyClass +# 5| 4: [InstanceConstructor,PrimaryConstructor] MyClass +# 7| 5: [Method] ToString +# 7| -1: [TypeMention] string +# 8| 4: [BlockStmt] {...} +# 9| 0: [ReturnStmt] return ...; +# 9| 0: [StringLiteralUtf16] "tainted" +# 13| 6: [Method] Sink +# 13| -1: [TypeMention] Void +#-----| 2: (Parameters) +# 13| 0: [Parameter] o +# 13| -1: [TypeMention] object +# 13| 4: [BlockStmt] {...} +# 15| 7: [Method] M1 +# 15| -1: [TypeMention] Void +# 16| 4: [BlockStmt] {...} +# 17| 0: [LocalVariableDeclStmt] ... ...; +# 17| 0: [LocalVariableDeclAndInitExpr] MyClass x1 = ... +# 17| -1: [TypeMention] MyClass +# 17| 0: [LocalVariableAccess] access to local variable x1 +# 17| 1: [ObjectCreation] object creation of type MyClass +# 17| 0: [TypeMention] MyClass +# 18| 1: [LocalVariableDeclStmt] ... ...; +# 18| 0: [LocalVariableDeclAndInitExpr] String x2 = ... +# 18| -1: [TypeMention] string +# 18| 0: [LocalVariableAccess] access to local variable x2 +# 18| 1: [AddExpr] ... + ... +# 18| 0: [StringLiteralUtf16] "Hello" +# 18| 1: [MethodCall] call to method ToString +# 18| -1: [LocalVariableAccess] access to local variable x1 +# 19| 2: [ExprStmt] ...; +# 19| 0: [MethodCall] call to method Sink +# 19| 0: [LocalVariableAccess] access to local variable x2 +# 22| 8: [Method] M2 +# 22| -1: [TypeMention] Void +# 23| 4: [BlockStmt] {...} +# 24| 0: [LocalVariableDeclStmt] ... ...; +# 24| 0: [LocalVariableDeclAndInitExpr] MyClass x1 = ... +# 24| -1: [TypeMention] MyClass +# 24| 0: [LocalVariableAccess] access to local variable x1 +# 24| 1: [ObjectCreation] object creation of type MyClass +# 24| 0: [TypeMention] MyClass +# 25| 1: [LocalVariableDeclStmt] ... ...; +# 25| 0: [LocalVariableDeclAndInitExpr] String x2 = ... +# 25| -1: [TypeMention] string +# 25| 0: [LocalVariableAccess] access to local variable x2 +# 25| 1: [AddExpr] ... + ... +# 25| 0: [StringLiteralUtf16] "Hello" +# 26| 2: [ExprStmt] ...; +# 26| 0: [MethodCall] call to method Sink +# 26| 0: [LocalVariableAccess] access to local variable x2 +# 29| 9: [Method] M3 +# 29| -1: [TypeMention] Void +# 30| 4: [BlockStmt] {...} +# 31| 0: [LocalVariableDeclStmt] ... ...; +# 31| 0: [LocalVariableDeclAndInitExpr] MyClass x1 = ... +# 31| -1: [TypeMention] MyClass +# 31| 0: [LocalVariableAccess] access to local variable x1 +# 31| 1: [ObjectCreation] object creation of type MyClass +# 31| 0: [TypeMention] MyClass +# 32| 1: [LocalVariableDeclStmt] ... ...; +# 32| 0: [LocalVariableDeclAndInitExpr] String x2 = ... +# 32| -1: [TypeMention] string +# 32| 0: [LocalVariableAccess] access to local variable x2 +# 32| 1: [InterpolatedStringExpr] $"..." +# 32| 0: [StringLiteralUtf16] "Hello " +# 32| 1: [MethodCall] call to method ToString +# 32| -1: [LocalVariableAccess] access to local variable x1 +# 33| 2: [ExprStmt] ...; +# 33| 0: [MethodCall] call to method Sink +# 33| 0: [LocalVariableAccess] access to local variable x2 +# 36| 10: [Method] M4 +# 36| -1: [TypeMention] Void +# 37| 4: [BlockStmt] {...} +# 38| 0: [LocalVariableDeclStmt] ... ...; +# 38| 0: [LocalVariableDeclAndInitExpr] MyClass x1 = ... +# 38| -1: [TypeMention] MyClass +# 38| 0: [LocalVariableAccess] access to local variable x1 +# 38| 1: [ObjectCreation] object creation of type MyClass +# 38| 0: [TypeMention] MyClass +# 39| 1: [LocalVariableDeclStmt] ... ...; +# 39| 0: [LocalVariableDeclAndInitExpr] String x2 = ... +# 39| -1: [TypeMention] string +# 39| 0: [LocalVariableAccess] access to local variable x2 +# 39| 1: [InterpolatedStringExpr] $"..." +# 39| 0: [StringLiteralUtf16] "Hello " +# 40| 2: [ExprStmt] ...; +# 40| 0: [MethodCall] call to method Sink +# 40| 0: [LocalVariableAccess] access to local variable x2 +# 25| [LocalVariableAccess] access to local variable x1 +# 39| [LocalVariableAccess] access to local variable x1 diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.qlref b/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.qlref new file mode 100644 index 000000000000..f867dd01f9f8 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.qlref @@ -0,0 +1 @@ +shared/PrintAst.ql \ No newline at end of file From 53c2f76385fd56e232e1ae85e0f796bd8ad5b298 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 9 Jan 2025 13:04:47 +0100 Subject: [PATCH 09/22] C#: Update AST printing to include generated cast (wrapping) expressions and generated ToString calls. --- csharp/ql/lib/semmle/code/csharp/PrintAst.qll | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/csharp/ql/lib/semmle/code/csharp/PrintAst.qll b/csharp/ql/lib/semmle/code/csharp/PrintAst.qll index 281e157975ab..fd4bf1cb86b0 100644 --- a/csharp/ql/lib/semmle/code/csharp/PrintAst.qll +++ b/csharp/ql/lib/semmle/code/csharp/PrintAst.qll @@ -32,7 +32,9 @@ private predicate shouldPrint(Element e, Location l) { } private predicate isImplicitExpression(ControlFlowElement element) { - element.(Expr).isImplicit() and + // Include compiler generated cast expressions and `ToString` calls if + // they wrap actual source expressions. + element.(Expr).stripImplicit().isImplicit() and not element instanceof CastExpr and not element.(OperatorCall).getTarget() instanceof ImplicitConversionOperator and not element instanceof ElementInitializer From f239ab1fbf046dcb4202cce67eda3449ab0dc4c4 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 9 Jan 2025 13:52:37 +0100 Subject: [PATCH 10/22] C#: Update PrintAst expected test output. --- .../dataflow/implicittostring/PrintAst.expected | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected b/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected index 7b3215415230..bf2a515a8895 100644 --- a/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected +++ b/csharp/ql/test/library-tests/dataflow/implicittostring/PrintAst.expected @@ -48,6 +48,8 @@ implicitToString.cs: # 25| 0: [LocalVariableAccess] access to local variable x2 # 25| 1: [AddExpr] ... + ... # 25| 0: [StringLiteralUtf16] "Hello" +# 25| 1: [MethodCall] call to method ToString +# 25| -1: [LocalVariableAccess] access to local variable x1 # 26| 2: [ExprStmt] ...; # 26| 0: [MethodCall] call to method Sink # 26| 0: [LocalVariableAccess] access to local variable x2 @@ -86,8 +88,8 @@ implicitToString.cs: # 39| 0: [LocalVariableAccess] access to local variable x2 # 39| 1: [InterpolatedStringExpr] $"..." # 39| 0: [StringLiteralUtf16] "Hello " +# 39| 1: [MethodCall] call to method ToString +# 39| -1: [LocalVariableAccess] access to local variable x1 # 40| 2: [ExprStmt] ...; # 40| 0: [MethodCall] call to method Sink # 40| 0: [LocalVariableAccess] access to local variable x2 -# 25| [LocalVariableAccess] access to local variable x1 -# 39| [LocalVariableAccess] access to local variable x1 From 20c2b2b2a27af5cfc1a66193a9ea85a943cf0be7 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 9 Jan 2025 11:40:42 +0100 Subject: [PATCH 11/22] C#: Update other existing tests expected output. --- .../controlflow/graph/BasicBlock.expected | 6 +++--- .../controlflow/graph/Dominance.expected | 18 ++++++++++++------ .../graph/EnclosingCallable.expected | 3 +++ .../controlflow/graph/EntryElement.expected | 3 +++ .../controlflow/graph/ExitElement.expected | 3 +++ .../controlflow/graph/NodeGraph.expected | 9 ++++++--- .../csharp6/InterpolatedStringExpr.expected | 4 ++-- .../csharp6/MemberAccess.expected | 2 ++ .../library-tests/csharp6/PrintAst.expected | 18 ++++++++++-------- .../library-tests/csharp7.3/PrintAst.expected | 3 ++- .../test/library-tests/csharp7/IsFlow.expected | 6 ++++-- .../csharp7/LocalTaintFlow.expected | 6 +++--- .../library-tests/csharp7/PrintAst.expected | 9 ++++++--- .../AlternateInterpolatedStrings.expected | 4 ++-- .../library-tests/csharp8/PrintAst.expected | 6 ++++-- .../dataflow/global/GetAnOutNode.expected | 1 + .../dataflow/global/TaintTrackingPath.expected | 6 +++++- .../flowsources/StoredFlowSources.expected | 1 + 18 files changed, 72 insertions(+), 36 deletions(-) diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index 527816c645be..af76384a3072 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -859,7 +859,7 @@ | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:8:18:8:23 | Int32 i1 | 8 | | Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:8:13:8:23 | [false] ... is ... | 1 | | Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:8:13:8:23 | [true] ... is ... | 1 | -| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:42 | call to method WriteLine | 6 | +| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:42 | call to method WriteLine | 7 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:23:12:31 | String s1 | 3 | | Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:12:18:12:31 | [false] ... is ... | 1 | | Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:12:18:12:31 | [true] ... is ... | 1 | @@ -872,9 +872,9 @@ | Patterns.cs:23:17:23:22 | break; | Patterns.cs:23:17:23:22 | break; | 1 | | Patterns.cs:24:13:24:36 | case ...: | Patterns.cs:24:18:24:23 | Int32 i2 | 2 | | Patterns.cs:24:30:24:31 | access to local variable i2 | Patterns.cs:24:30:24:35 | ... > ... | 3 | -| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:26:17:26:22 | break; | 6 | +| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:26:17:26:22 | break; | 7 | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | 2 | -| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:29:17:29:22 | break; | 6 | +| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:29:17:29:22 | break; | 7 | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | 2 | | Patterns.cs:31:17:31:50 | ...; | Patterns.cs:32:17:32:22 | break; | 6 | | Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:33:18:33:23 | Object v2 | 2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 9a1a38b7935a..23a62d593d76 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -3147,7 +3147,8 @@ dominance | Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:33:10:36 | "int " | | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:13:10:42 | call to method WriteLine | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:38:10:39 | access to local variable i1 | -| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:31:10:41 | $"..." | +| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:38:10:39 | call to method ToString | +| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:10:31:10:41 | $"..." | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:18 | access to local variable o | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:23:12:31 | String s1 | | Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | @@ -3179,7 +3180,8 @@ dominance | Patterns.cs:25:17:25:52 | ...; | Patterns.cs:25:37:25:45 | "positive " | | Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:17:25:51 | call to method WriteLine | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:47:25:48 | access to local variable i2 | -| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:35:25:50 | $"..." | +| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:47:25:48 | call to method ToString | +| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:25:35:25:50 | $"..." | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:28:17:28:47 | ...; | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:30:13:30:27 | case ...: | @@ -3187,7 +3189,8 @@ dominance | Patterns.cs:28:17:28:47 | ...; | Patterns.cs:28:37:28:40 | "int " | | Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:17:28:46 | call to method WriteLine | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:42:28:43 | access to local variable i3 | -| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:35:28:45 | $"..." | +| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:42:28:43 | call to method ToString | +| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:28:35:28:45 | $"..." | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:31:17:31:50 | ...; | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:33:13:33:24 | case ...: | @@ -7341,9 +7344,10 @@ postDominance | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:8:13:8:23 | [true] ... is ... | | Patterns.cs:10:13:10:42 | call to method WriteLine | Patterns.cs:10:31:10:41 | $"..." | | Patterns.cs:10:13:10:43 | ...; | Patterns.cs:9:9:11:9 | {...} | -| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:38:10:39 | access to local variable i1 | +| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:38:10:39 | call to method ToString | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:13:10:43 | ...; | | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:33:10:36 | "int " | +| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:10:38:10:39 | access to local variable i1 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:8:13:8:23 | [false] ... is ... | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:14:18:9 | if (...) ... | | Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:18:12:18 | access to local variable o | @@ -7368,15 +7372,17 @@ postDominance | Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:24:35:24:35 | 0 | | Patterns.cs:24:35:24:35 | 0 | Patterns.cs:24:30:24:31 | access to local variable i2 | | Patterns.cs:25:17:25:51 | call to method WriteLine | Patterns.cs:25:35:25:50 | $"..." | -| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:47:25:48 | access to local variable i2 | +| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:47:25:48 | call to method ToString | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:17:25:52 | ...; | | Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:37:25:45 | "positive " | +| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:25:47:25:48 | access to local variable i2 | | Patterns.cs:26:17:26:22 | break; | Patterns.cs:25:17:25:51 | call to method WriteLine | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:27:13:27:24 | case ...: | | Patterns.cs:28:17:28:46 | call to method WriteLine | Patterns.cs:28:35:28:45 | $"..." | -| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:42:28:43 | access to local variable i3 | +| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:42:28:43 | call to method ToString | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:17:28:47 | ...; | | Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:37:28:40 | "int " | +| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:28:42:28:43 | access to local variable i3 | | Patterns.cs:29:17:29:22 | break; | Patterns.cs:28:17:28:46 | call to method WriteLine | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:30:13:30:27 | case ...: | | Patterns.cs:31:17:31:49 | call to method WriteLine | Patterns.cs:31:35:31:48 | $"..." | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index 9edc62925d86..e5d4e3c733d4 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -3437,6 +3437,7 @@ nodeEnclosing | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:5:10:5:11 | M1 | @@ -3469,6 +3470,7 @@ nodeEnclosing | Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:26:17:26:22 | break; | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:5:10:5:11 | M1 | @@ -3477,6 +3479,7 @@ nodeEnclosing | Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:5:10:5:11 | M1 | +| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:29:17:29:22 | break; | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:5:10:5:11 | M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index fddab21f2b62..04e93332380c 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -2239,6 +2239,7 @@ | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:33:10:36 | "int " | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:33:10:36 | "int " | | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:38:10:39 | access to local variable i1 | +| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:10:38:10:39 | access to local variable i1 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:14:18:9 | if (...) ... | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:18:12:18 | access to local variable o | | Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:12:18:12:18 | access to local variable o | @@ -2269,6 +2270,7 @@ | Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:37:25:45 | "positive " | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:37:25:45 | "positive " | | Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:47:25:48 | access to local variable i2 | +| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:25:47:25:48 | access to local variable i2 | | Patterns.cs:26:17:26:22 | break; | Patterns.cs:26:17:26:22 | break; | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:13:27:24 | case ...: | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:27:18:27:23 | Int32 i3 | @@ -2277,6 +2279,7 @@ | Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:37:28:40 | "int " | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:37:28:40 | "int " | | Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:42:28:43 | access to local variable i3 | +| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:28:42:28:43 | access to local variable i3 | | Patterns.cs:29:17:29:22 | break; | Patterns.cs:29:17:29:22 | break; | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:13:30:27 | case ...: | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:30:18:30:26 | String s2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index 81ee139f6a68..e8c8a1f75a7f 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -2912,6 +2912,7 @@ | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:31:10:41 | $"..." | normal | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:33:10:36 | "int " | normal | | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:38:10:39 | access to local variable i1 | normal | +| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:10:38:10:39 | call to method ToString | normal | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:14:13:14:45 | call to method WriteLine | normal | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | ... is ... | false | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:17:9:18:9 | {...} | normal | @@ -2960,6 +2961,7 @@ | Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:35:25:50 | $"..." | normal | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:37:25:45 | "positive " | normal | | Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:47:25:48 | access to local variable i2 | normal | +| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:25:47:25:48 | call to method ToString | normal | | Patterns.cs:26:17:26:22 | break; | Patterns.cs:26:17:26:22 | break; | break | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | no-match | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:28:17:28:46 | call to method WriteLine | normal | @@ -2970,6 +2972,7 @@ | Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:35:28:45 | $"..." | normal | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:37:28:40 | "int " | normal | | Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:42:28:43 | access to local variable i3 | normal | +| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:28:42:28:43 | call to method ToString | normal | | Patterns.cs:29:17:29:22 | break; | Patterns.cs:29:17:29:22 | break; | break | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | no-match | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:31:17:31:49 | call to method WriteLine | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 0078ba76213d..53fc61f9bc4f 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -3528,7 +3528,8 @@ | Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:33:10:36 | "int " | | | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:13:10:42 | call to method WriteLine | | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:38:10:39 | access to local variable i1 | | -| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:31:10:41 | $"..." | | +| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:38:10:39 | call to method ToString | | +| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:10:31:10:41 | $"..." | | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:18 | access to local variable o | | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:23:12:31 | String s1 | | | Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | false | @@ -3565,7 +3566,8 @@ | Patterns.cs:25:17:25:52 | ...; | Patterns.cs:25:37:25:45 | "positive " | | | Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:17:25:51 | call to method WriteLine | | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:47:25:48 | access to local variable i2 | | -| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:35:25:50 | $"..." | | +| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:47:25:48 | call to method ToString | | +| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:25:35:25:50 | $"..." | | | Patterns.cs:26:17:26:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | break | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:28:17:28:47 | ...; | match | @@ -3574,7 +3576,8 @@ | Patterns.cs:28:17:28:47 | ...; | Patterns.cs:28:37:28:40 | "int " | | | Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:17:28:46 | call to method WriteLine | | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:42:28:43 | access to local variable i3 | | -| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:35:28:45 | $"..." | | +| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:42:28:43 | call to method ToString | | +| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:28:35:28:45 | $"..." | | | Patterns.cs:29:17:29:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | break | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:31:17:31:50 | ...; | match | diff --git a/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected b/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected index d10365546bd9..ce0b425c1137 100644 --- a/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected +++ b/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected @@ -4,11 +4,11 @@ | csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:47:25:52 | ", and " | | csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:54:25:64 | nameof(...) | | csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:66:25:77 | " has length " | -| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:79:25:94 | ... ?? ... | +| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:79:25:94 | call to method ToString | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:20:27:30 | nameof(...) | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:32:27:35 | " is " | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:37:27:39 | access to local variable foo | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:41:27:46 | ", and " | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:48:27:58 | nameof(...) | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:60:27:71 | " has length " | -| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:73:27:88 | ... ?? ... | +| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:73:27:88 | call to method ToString | diff --git a/csharp/ql/test/library-tests/csharp6/MemberAccess.expected b/csharp/ql/test/library-tests/csharp6/MemberAccess.expected index 1eda117fadd2..c37ea475cbaf 100644 --- a/csharp/ql/test/library-tests/csharp6/MemberAccess.expected +++ b/csharp/ql/test/library-tests/csharp6/MemberAccess.expected @@ -4,6 +4,8 @@ memberAccess | csharp6.cs:32:38:32:70 | access to indexer | csharp6.cs:32:38:32:66 | object creation of type Dictionary | Conditional | | csharp6.cs:32:38:32:73 | access to indexer | csharp6.cs:32:38:32:70 | access to indexer | Unconditional | methodCall +| csharp6.cs:25:79:25:94 | call to method ToString | csharp6.cs:25:79:25:94 | ... ?? ... | Unconditional | +| csharp6.cs:27:73:27:88 | call to method ToString | csharp6.cs:27:73:27:88 | ... ?? ... | Unconditional | | csharp6.cs:30:31:30:44 | call to method ToUpper | csharp6.cs:30:31:30:33 | access to local variable foo | Conditional | extensionMethodCall | csharp6.cs:29:35:29:44 | call to method Any | csharp6.cs:29:35:29:37 | access to local variable bar | Conditional | diff --git a/csharp/ql/test/library-tests/csharp6/PrintAst.expected b/csharp/ql/test/library-tests/csharp6/PrintAst.expected index 892ad6dd4b15..2daa487d8a43 100644 --- a/csharp/ql/test/library-tests/csharp6/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp6/PrintAst.expected @@ -38,10 +38,11 @@ csharp6.cs: # 25| 4: [NameOfExpr] nameof(...) # 25| 0: [LocalVariableAccess] access to local variable bar # 25| 5: [StringLiteralUtf16] " has length " -# 25| 6: [NullCoalescingExpr] ... ?? ... -# 25| 0: [PropertyCall] access to property Length -# 25| -1: [LocalVariableAccess] access to local variable bar -# 25| 1: [IntLiteral] 0 +# 25| 6: [MethodCall] call to method ToString +# 25| -1: [NullCoalescingExpr] ... ?? ... +# 25| 0: [PropertyCall] access to property Length +# 25| -1: [LocalVariableAccess] access to local variable bar +# 25| 1: [IntLiteral] 0 # 27| 2: [ExprStmt] ...; # 27| 0: [MethodCall] call to method Fn # 27| 0: [InterpolatedStringExpr] $"..." @@ -53,10 +54,11 @@ csharp6.cs: # 27| 4: [NameOfExpr] nameof(...) # 27| 0: [LocalVariableAccess] access to local variable bar # 27| 5: [StringLiteralUtf16] " has length " -# 27| 6: [NullCoalescingExpr] ... ?? ... -# 27| 0: [PropertyCall] access to property Length -# 27| -1: [LocalVariableAccess] access to local variable bar -# 27| 1: [IntLiteral] 0 +# 27| 6: [MethodCall] call to method ToString +# 27| -1: [NullCoalescingExpr] ... ?? ... +# 27| 0: [PropertyCall] access to property Length +# 27| -1: [LocalVariableAccess] access to local variable bar +# 27| 1: [IntLiteral] 0 # 29| 3: [LocalVariableDeclStmt] ... ...; # 29| 0: [LocalVariableDeclAndInitExpr] Nullable anythingInBar = ... # 29| -1: [TypeMention] bool? diff --git a/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected b/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected index d55d5d279ada..d693af41f714 100644 --- a/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected @@ -110,4 +110,5 @@ csharp73.cs: # 51| 0: [TypeMention] Console # 51| 0: [InterpolatedStringExpr] $"..." # 51| 0: [StringLiteralUtf16] "x is " -# 51| 1: [LocalVariableAccess] access to local variable x +# 51| 1: [MethodCall] call to method ToString +# 51| -1: [LocalVariableAccess] access to local variable x diff --git a/csharp/ql/test/library-tests/csharp7/IsFlow.expected b/csharp/ql/test/library-tests/csharp7/IsFlow.expected index b3e283528457..1640c8ee678e 100644 --- a/csharp/ql/test/library-tests/csharp7/IsFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/IsFlow.expected @@ -37,7 +37,8 @@ | CSharp7.cs:258:17:258:52 | ...; | CSharp7.cs:258:37:258:45 | "positive " | semmle.label | successor | | CSharp7.cs:258:35:258:50 | $"..." | CSharp7.cs:258:17:258:51 | call to method WriteLine | semmle.label | successor | | CSharp7.cs:258:37:258:45 | "positive " | CSharp7.cs:258:47:258:48 | access to local variable i2 | semmle.label | successor | -| CSharp7.cs:258:47:258:48 | access to local variable i2 | CSharp7.cs:258:35:258:50 | $"..." | semmle.label | successor | +| CSharp7.cs:258:47:258:48 | access to local variable i2 | CSharp7.cs:258:47:258:48 | call to method ToString | semmle.label | successor | +| CSharp7.cs:258:47:258:48 | call to method ToString | CSharp7.cs:258:35:258:50 | $"..." | semmle.label | successor | | CSharp7.cs:259:17:259:22 | break; | CSharp7.cs:230:10:230:13 | exit Test (normal) | semmle.label | break | | CSharp7.cs:260:13:260:24 | case ...: | CSharp7.cs:260:18:260:23 | Int32 i3 | semmle.label | successor | | CSharp7.cs:260:18:260:23 | Int32 i3 | CSharp7.cs:261:17:261:47 | ...; | semmle.label | match | @@ -46,7 +47,8 @@ | CSharp7.cs:261:17:261:47 | ...; | CSharp7.cs:261:37:261:40 | "int " | semmle.label | successor | | CSharp7.cs:261:35:261:45 | $"..." | CSharp7.cs:261:17:261:46 | call to method WriteLine | semmle.label | successor | | CSharp7.cs:261:37:261:40 | "int " | CSharp7.cs:261:42:261:43 | access to local variable i3 | semmle.label | successor | -| CSharp7.cs:261:42:261:43 | access to local variable i3 | CSharp7.cs:261:35:261:45 | $"..." | semmle.label | successor | +| CSharp7.cs:261:42:261:43 | access to local variable i3 | CSharp7.cs:261:42:261:43 | call to method ToString | semmle.label | successor | +| CSharp7.cs:261:42:261:43 | call to method ToString | CSharp7.cs:261:35:261:45 | $"..." | semmle.label | successor | | CSharp7.cs:262:17:262:22 | break; | CSharp7.cs:230:10:230:13 | exit Test (normal) | semmle.label | break | | CSharp7.cs:263:13:263:27 | case ...: | CSharp7.cs:263:18:263:26 | String s2 | semmle.label | successor | | CSharp7.cs:263:18:263:26 | String s2 | CSharp7.cs:264:17:264:50 | ...; | semmle.label | match | diff --git a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected index 4a16e2491dfe..d860099ca203 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected @@ -254,7 +254,7 @@ | CSharp7.cs:233:28:233:33 | ... > ... | CSharp7.cs:233:13:233:33 | [true] ... && ... | | CSharp7.cs:235:13:235:42 | [input] SSA phi read(o) | CSharp7.cs:248:9:274:9 | SSA phi read(o) | | CSharp7.cs:235:33:235:36 | "int " | CSharp7.cs:235:31:235:41 | $"..." | -| CSharp7.cs:235:38:235:39 | access to local variable i1 | CSharp7.cs:235:31:235:41 | $"..." | +| CSharp7.cs:235:38:235:39 | call to method ToString | CSharp7.cs:235:31:235:41 | $"..." | | CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:237:23:237:31 | String s1 | | CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:239:13:239:45 | [input] SSA phi read(o) | | CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:241:18:241:18 | access to local variable o | @@ -289,11 +289,11 @@ | CSharp7.cs:257:30:257:31 | access to local variable i2 | CSharp7.cs:257:30:257:35 | ... > ... | | CSharp7.cs:257:30:257:31 | access to local variable i2 | CSharp7.cs:258:47:258:48 | access to local variable i2 | | CSharp7.cs:258:37:258:45 | "positive " | CSharp7.cs:258:35:258:50 | $"..." | -| CSharp7.cs:258:47:258:48 | access to local variable i2 | CSharp7.cs:258:35:258:50 | $"..." | +| CSharp7.cs:258:47:258:48 | call to method ToString | CSharp7.cs:258:35:258:50 | $"..." | | CSharp7.cs:260:18:260:23 | Int32 i3 | CSharp7.cs:260:18:260:23 | SSA def(i3) | | CSharp7.cs:260:18:260:23 | SSA def(i3) | CSharp7.cs:261:42:261:43 | access to local variable i3 | | CSharp7.cs:261:37:261:40 | "int " | CSharp7.cs:261:35:261:45 | $"..." | -| CSharp7.cs:261:42:261:43 | access to local variable i3 | CSharp7.cs:261:35:261:45 | $"..." | +| CSharp7.cs:261:42:261:43 | call to method ToString | CSharp7.cs:261:35:261:45 | $"..." | | CSharp7.cs:263:18:263:26 | SSA def(s2) | CSharp7.cs:264:45:264:46 | access to local variable s2 | | CSharp7.cs:263:18:263:26 | String s2 | CSharp7.cs:263:18:263:26 | SSA def(s2) | | CSharp7.cs:264:37:264:43 | "string " | CSharp7.cs:264:35:264:48 | $"..." | diff --git a/csharp/ql/test/library-tests/csharp7/PrintAst.expected b/csharp/ql/test/library-tests/csharp7/PrintAst.expected index e5d009e0df63..dd00d798f44d 100644 --- a/csharp/ql/test/library-tests/csharp7/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp7/PrintAst.expected @@ -727,7 +727,8 @@ CSharp7.cs: # 235| 0: [TypeMention] Console # 235| 0: [InterpolatedStringExpr] $"..." # 235| 0: [StringLiteralUtf16] "int " -# 235| 1: [LocalVariableAccess] access to local variable i1 +# 235| 1: [MethodCall] call to method ToString +# 235| -1: [LocalVariableAccess] access to local variable i1 # 237| 2: [IfStmt] if (...) ... # 237| 0: [IsExpr] ... is ... # 237| 0: [LocalVariableAccess] access to local variable o @@ -789,7 +790,8 @@ CSharp7.cs: # 258| 0: [TypeMention] Console # 258| 0: [InterpolatedStringExpr] $"..." # 258| 0: [StringLiteralUtf16] "positive " -# 258| 1: [LocalVariableAccess] access to local variable i2 +# 258| 1: [MethodCall] call to method ToString +# 258| -1: [LocalVariableAccess] access to local variable i2 # 259| 9: [BreakStmt] break; # 260| 10: [CaseStmt] case ...: # 260| 0: [VariablePatternExpr] Int32 i3 @@ -800,7 +802,8 @@ CSharp7.cs: # 261| 0: [TypeMention] Console # 261| 0: [InterpolatedStringExpr] $"..." # 261| 0: [StringLiteralUtf16] "int " -# 261| 1: [LocalVariableAccess] access to local variable i3 +# 261| 1: [MethodCall] call to method ToString +# 261| -1: [LocalVariableAccess] access to local variable i3 # 262| 12: [BreakStmt] break; # 263| 13: [CaseStmt] case ...: # 263| 0: [VariablePatternExpr] String s2 diff --git a/csharp/ql/test/library-tests/csharp8/AlternateInterpolatedStrings.expected b/csharp/ql/test/library-tests/csharp8/AlternateInterpolatedStrings.expected index 06e2f93cbe36..5e065aa35819 100644 --- a/csharp/ql/test/library-tests/csharp8/AlternateInterpolatedStrings.expected +++ b/csharp/ql/test/library-tests/csharp8/AlternateInterpolatedStrings.expected @@ -1,6 +1,6 @@ inserts -| AlternateInterpolatedStrings.cs:5:17:5:26 | $"..." | 1 | AlternateInterpolatedStrings.cs:5:23:5:24 | 12 | -| AlternateInterpolatedStrings.cs:6:17:6:26 | $"..." | 1 | AlternateInterpolatedStrings.cs:6:23:6:24 | 12 | +| AlternateInterpolatedStrings.cs:5:17:5:26 | $"..." | 1 | AlternateInterpolatedStrings.cs:5:23:5:24 | call to method ToString | +| AlternateInterpolatedStrings.cs:6:17:6:26 | $"..." | 1 | AlternateInterpolatedStrings.cs:6:23:6:24 | call to method ToString | text | AlternateInterpolatedStrings.cs:5:17:5:26 | $"..." | 0 | AlternateInterpolatedStrings.cs:5:20:5:21 | "C:" | | AlternateInterpolatedStrings.cs:6:17:6:26 | $"..." | 0 | AlternateInterpolatedStrings.cs:6:20:6:21 | "C:" | diff --git a/csharp/ql/test/library-tests/csharp8/PrintAst.expected b/csharp/ql/test/library-tests/csharp8/PrintAst.expected index c33374e4761d..bdf063f624ec 100644 --- a/csharp/ql/test/library-tests/csharp8/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp8/PrintAst.expected @@ -4,12 +4,14 @@ AlternateInterpolatedStrings.cs: # 5| -1: [TypeMention] string # 5| 1: [InterpolatedStringExpr] $"..." # 5| 0: [StringLiteralUtf16] "C:" -# 5| 1: [IntLiteral] 12 +# 5| 1: [MethodCall] call to method ToString +# 5| -1: [IntLiteral] 12 # 6| 6: [Field] s2 # 6| -1: [TypeMention] string # 6| 1: [InterpolatedStringExpr] $"..." # 6| 0: [StringLiteralUtf16] "C:" -# 6| 1: [IntLiteral] 12 +# 6| 1: [MethodCall] call to method ToString +# 6| -1: [IntLiteral] 12 AsyncStreams.cs: # 6| [Class] AsyncStreams # 8| 5: [Method] Items diff --git a/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected b/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected index ca13350d527b..643b3e813503 100644 --- a/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected +++ b/csharp/ql/test/library-tests/dataflow/global/GetAnOutNode.expected @@ -176,6 +176,7 @@ | GlobalDataFlowStringBuilder.cs:36:21:36:34 | call to method ToString | normal | GlobalDataFlowStringBuilder.cs:36:21:36:34 | call to method ToString | | GlobalDataFlowStringBuilder.cs:39:19:39:37 | object creation of type StringBuilder | normal | GlobalDataFlowStringBuilder.cs:39:19:39:37 | object creation of type StringBuilder | | GlobalDataFlowStringBuilder.cs:40:9:40:27 | call to method Append | normal | GlobalDataFlowStringBuilder.cs:40:9:40:27 | call to method Append | +| GlobalDataFlowStringBuilder.cs:40:23:40:24 | call to method ToString | normal | GlobalDataFlowStringBuilder.cs:40:23:40:24 | call to method ToString | | GlobalDataFlowStringBuilder.cs:41:21:41:34 | call to method ToString | normal | GlobalDataFlowStringBuilder.cs:41:21:41:34 | call to method ToString | | GlobalDataFlowStringBuilder.cs:44:9:44:18 | call to method Clear | normal | GlobalDataFlowStringBuilder.cs:44:9:44:18 | call to method Clear | | GlobalDataFlowStringBuilder.cs:45:23:45:35 | call to method ToString | normal | GlobalDataFlowStringBuilder.cs:45:23:45:35 | call to method ToString | diff --git a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected index f90f71d1ea95..6aa705824b79 100644 --- a/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected +++ b/csharp/ql/test/library-tests/dataflow/global/TaintTrackingPath.expected @@ -514,7 +514,7 @@ edges | GlobalDataFlowStringBuilder.cs:24:19:24:26 | (...) ... : AppendInterpolatedStringHandler | GlobalDataFlowStringBuilder.cs:24:9:24:10 | [post] access to parameter sb : StringBuilder | provenance | MaD:16 | | GlobalDataFlowStringBuilder.cs:30:31:30:32 | [post] access to local variable sb : StringBuilder | GlobalDataFlowStringBuilder.cs:31:21:31:22 | access to local variable sb : StringBuilder | provenance | | | GlobalDataFlowStringBuilder.cs:30:31:30:32 | [post] access to local variable sb : StringBuilder | GlobalDataFlowStringBuilder.cs:35:20:35:21 | access to local variable sb : StringBuilder | provenance | | -| GlobalDataFlowStringBuilder.cs:30:31:30:32 | [post] access to local variable sb : StringBuilder | GlobalDataFlowStringBuilder.cs:40:20:40:26 | (...) ... : AppendInterpolatedStringHandler | provenance | | +| GlobalDataFlowStringBuilder.cs:30:31:30:32 | [post] access to local variable sb : StringBuilder | GlobalDataFlowStringBuilder.cs:40:23:40:24 | access to local variable sb : StringBuilder | provenance | | | GlobalDataFlowStringBuilder.cs:30:35:30:48 | "taint source" : String | GlobalDataFlowStringBuilder.cs:17:64:17:64 | s : String | provenance | | | GlobalDataFlowStringBuilder.cs:30:35:30:48 | "taint source" : String | GlobalDataFlowStringBuilder.cs:30:31:30:32 | [post] access to local variable sb : StringBuilder | provenance | MaD:14 | | GlobalDataFlowStringBuilder.cs:31:13:31:17 | access to local variable sink0 : String | GlobalDataFlowStringBuilder.cs:32:15:32:19 | access to local variable sink0 | provenance | | @@ -527,6 +527,8 @@ edges | GlobalDataFlowStringBuilder.cs:36:21:36:34 | call to method ToString : String | GlobalDataFlowStringBuilder.cs:36:13:36:17 | access to local variable sink1 : String | provenance | | | GlobalDataFlowStringBuilder.cs:40:9:40:11 | [post] access to local variable sb2 : StringBuilder | GlobalDataFlowStringBuilder.cs:41:21:41:23 | access to local variable sb2 : StringBuilder | provenance | | | GlobalDataFlowStringBuilder.cs:40:20:40:26 | (...) ... : AppendInterpolatedStringHandler | GlobalDataFlowStringBuilder.cs:40:9:40:11 | [post] access to local variable sb2 : StringBuilder | provenance | MaD:16 | +| GlobalDataFlowStringBuilder.cs:40:23:40:24 | access to local variable sb : StringBuilder | GlobalDataFlowStringBuilder.cs:40:23:40:24 | call to method ToString : String | provenance | MaD:17 | +| GlobalDataFlowStringBuilder.cs:40:23:40:24 | call to method ToString : String | GlobalDataFlowStringBuilder.cs:40:20:40:26 | (...) ... : AppendInterpolatedStringHandler | provenance | | | GlobalDataFlowStringBuilder.cs:41:13:41:17 | access to local variable sink2 : String | GlobalDataFlowStringBuilder.cs:42:15:42:19 | access to local variable sink2 | provenance | | | GlobalDataFlowStringBuilder.cs:41:21:41:23 | access to local variable sb2 : StringBuilder | GlobalDataFlowStringBuilder.cs:41:21:41:34 | call to method ToString : String | provenance | MaD:17 | | GlobalDataFlowStringBuilder.cs:41:21:41:34 | call to method ToString : String | GlobalDataFlowStringBuilder.cs:41:13:41:17 | access to local variable sink2 : String | provenance | | @@ -1046,6 +1048,8 @@ nodes | GlobalDataFlowStringBuilder.cs:37:15:37:19 | access to local variable sink1 | semmle.label | access to local variable sink1 | | GlobalDataFlowStringBuilder.cs:40:9:40:11 | [post] access to local variable sb2 : StringBuilder | semmle.label | [post] access to local variable sb2 : StringBuilder | | GlobalDataFlowStringBuilder.cs:40:20:40:26 | (...) ... : AppendInterpolatedStringHandler | semmle.label | (...) ... : AppendInterpolatedStringHandler | +| GlobalDataFlowStringBuilder.cs:40:23:40:24 | access to local variable sb : StringBuilder | semmle.label | access to local variable sb : StringBuilder | +| GlobalDataFlowStringBuilder.cs:40:23:40:24 | call to method ToString : String | semmle.label | call to method ToString : String | | GlobalDataFlowStringBuilder.cs:41:13:41:17 | access to local variable sink2 : String | semmle.label | access to local variable sink2 : String | | GlobalDataFlowStringBuilder.cs:41:21:41:23 | access to local variable sb2 : StringBuilder | semmle.label | access to local variable sb2 : StringBuilder | | GlobalDataFlowStringBuilder.cs:41:21:41:34 | call to method ToString : String | semmle.label | call to method ToString : String | diff --git a/csharp/ql/test/library-tests/security/dataflow/flowsources/StoredFlowSources.expected b/csharp/ql/test/library-tests/security/dataflow/flowsources/StoredFlowSources.expected index 28156f12272e..e27ea53adbd1 100644 --- a/csharp/ql/test/library-tests/security/dataflow/flowsources/StoredFlowSources.expected +++ b/csharp/ql/test/library-tests/security/dataflow/flowsources/StoredFlowSources.expected @@ -6,6 +6,7 @@ | data.cs:28:35:28:71 | ... + ... | | data.cs:28:51:28:64 | access to local variable customerReader | | data.cs:28:51:28:71 | access to indexer | +| data.cs:28:51:28:71 | call to method ToString | | data.cs:30:13:30:26 | access to local variable customerReader | | entity.cs:31:29:31:82 | DbRawSqlQuery blogs = ... | | entity.cs:31:37:31:82 | call to method SqlQuery | From cd7d2d4ca4988102b028f3b221c7a5620389b0f4 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Thu, 9 Jan 2025 11:42:35 +0100 Subject: [PATCH 12/22] C#: Add change note. --- csharp/ql/lib/change-notes/2025-01-09-implicit-to-string.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 csharp/ql/lib/change-notes/2025-01-09-implicit-to-string.md diff --git a/csharp/ql/lib/change-notes/2025-01-09-implicit-to-string.md b/csharp/ql/lib/change-notes/2025-01-09-implicit-to-string.md new file mode 100644 index 000000000000..2956898841ee --- /dev/null +++ b/csharp/ql/lib/change-notes/2025-01-09-implicit-to-string.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Added extractor support for extracting implicit `ToString` calls in binary `+` expressions and string interpolation expressions. From 6a31fd7893f4743e631db302d9add41988a57d68 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 13 Jan 2025 09:52:14 +0100 Subject: [PATCH 13/22] C#: Add ImplicitToString example in nullness tests. --- .../ql/test/query-tests/Nullness/Implications.expected | 2 ++ .../ql/test/query-tests/Nullness/ImplicitToString.cs | 10 ++++++++++ .../ql/test/query-tests/Nullness/NullAlways.expected | 1 + csharp/ql/test/query-tests/Nullness/NullMaybe.expected | 3 +++ 4 files changed, 16 insertions(+) create mode 100644 csharp/ql/test/query-tests/Nullness/ImplicitToString.cs diff --git a/csharp/ql/test/query-tests/Nullness/Implications.expected b/csharp/ql/test/query-tests/Nullness/Implications.expected index b9c994d08250..45ffbc1d92b0 100644 --- a/csharp/ql/test/query-tests/Nullness/Implications.expected +++ b/csharp/ql/test/query-tests/Nullness/Implications.expected @@ -1451,6 +1451,8 @@ | GuardedString.cs:35:31:35:31 | access to local variable s | null | GuardedString.cs:7:20:7:32 | ... ? ... : ... | null | | GuardedString.cs:37:31:37:31 | access to local variable s | non-null | GuardedString.cs:7:20:7:32 | ... ? ... : ... | non-null | | GuardedString.cs:37:31:37:31 | access to local variable s | null | GuardedString.cs:7:20:7:32 | ... ? ... : ... | null | +| ImplicitToString.cs:8:23:8:23 | access to local variable o | non-null | ImplicitToString.cs:7:20:7:23 | null | non-null | +| ImplicitToString.cs:8:23:8:23 | access to local variable o | null | ImplicitToString.cs:7:20:7:23 | null | null | | NullAlwaysBad.cs:9:17:9:25 | ... != ... | false | NullAlwaysBad.cs:9:17:9:17 | access to parameter s | null | | NullAlwaysBad.cs:9:17:9:25 | ... != ... | true | NullAlwaysBad.cs:9:17:9:17 | access to parameter s | non-null | | NullAlwaysBad.cs:9:17:9:41 | ... \|\| ... | false | NullAlwaysBad.cs:9:17:9:25 | ... != ... | false | diff --git a/csharp/ql/test/query-tests/Nullness/ImplicitToString.cs b/csharp/ql/test/query-tests/Nullness/ImplicitToString.cs new file mode 100644 index 000000000000..304021520c2e --- /dev/null +++ b/csharp/ql/test/query-tests/Nullness/ImplicitToString.cs @@ -0,0 +1,10 @@ +using System; + +class ImplicitToStringTest +{ + void InterpolatedStringImplicitToString() + { + object o = null; + string s = $"{o}"; // GOOD + } +} diff --git a/csharp/ql/test/query-tests/Nullness/NullAlways.expected b/csharp/ql/test/query-tests/Nullness/NullAlways.expected index ec8a78e817b5..b52d6e6a4567 100644 --- a/csharp/ql/test/query-tests/Nullness/NullAlways.expected +++ b/csharp/ql/test/query-tests/Nullness/NullAlways.expected @@ -40,4 +40,5 @@ | E.cs:439:13:439:13 | access to parameter s | Variable $@ is always null at this dereference. | E.cs:435:29:435:29 | s | s | | Forwarding.cs:36:31:36:31 | access to local variable s | Variable $@ is always null at this dereference. | Forwarding.cs:7:16:7:16 | s | s | | Forwarding.cs:40:27:40:27 | access to local variable s | Variable $@ is always null at this dereference. | Forwarding.cs:7:16:7:16 | s | s | +| ImplicitToString.cs:8:23:8:23 | access to local variable o | Variable $@ is always null at this dereference. | ImplicitToString.cs:7:16:7:16 | o | o | | NullAlwaysBad.cs:9:30:9:30 | access to parameter s | Variable $@ is always null at this dereference. | NullAlwaysBad.cs:7:29:7:29 | s | s | diff --git a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected index 631c2cd77660..b1fa7702f8de 100644 --- a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected +++ b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected @@ -443,6 +443,8 @@ nodes | GuardedString.cs:34:9:37:40 | if (...) ... | | GuardedString.cs:34:26:34:26 | 0 | | GuardedString.cs:35:31:35:31 | access to local variable s | +| ImplicitToString.cs:7:16:7:23 | SSA def(o) | +| ImplicitToString.cs:8:23:8:23 | access to local variable o | | NullAlwaysBad.cs:7:29:7:29 | SSA param(s) | | NullAlwaysBad.cs:9:30:9:30 | access to parameter s | | NullMaybeBad.cs:7:27:7:27 | access to parameter o | @@ -837,6 +839,7 @@ edges | GuardedString.cs:31:26:31:27 | 10 | GuardedString.cs:34:9:37:40 | if (...) ... | | GuardedString.cs:34:9:37:40 | if (...) ... | GuardedString.cs:34:26:34:26 | 0 | | GuardedString.cs:34:26:34:26 | 0 | GuardedString.cs:35:31:35:31 | access to local variable s | +| ImplicitToString.cs:7:16:7:23 | SSA def(o) | ImplicitToString.cs:8:23:8:23 | access to local variable o | | NullAlwaysBad.cs:7:29:7:29 | SSA param(s) | NullAlwaysBad.cs:9:30:9:30 | access to parameter s | | NullMaybeBad.cs:13:17:13:20 | null | NullMaybeBad.cs:7:27:7:27 | access to parameter o | | Params.cs:20:12:20:15 | null | Params.cs:14:17:14:20 | access to parameter args | From e62846e4c579b8a0d9b6a9d851e9967c68443257 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 13 Jan 2025 09:53:51 +0100 Subject: [PATCH 14/22] C#: Disregard compiler generated method calls as possible null dereferences. --- csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll index f72f2dc59a13..a990455f4307 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/Nullness.qll @@ -526,7 +526,11 @@ class Dereference extends G::DereferenceableExpr { not underlyingType instanceof NullableType ) ) else ( - this = any(QualifiableExpr qe | not qe.isConditional()).getQualifier() and + this = + any(QualifiableExpr qe | + not qe.isConditional() and + not qe.(MethodCall).isImplicit() + ).getQualifier() and not this instanceof ThisAccess and not this instanceof BaseAccess and not this instanceof TypeAccess From d40c1bebbf8a97bd747a94976e911d48dc8e015f Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 13 Jan 2025 09:58:30 +0100 Subject: [PATCH 15/22] C#: Update expected testoutput for Nullness tests. --- csharp/ql/test/query-tests/Nullness/NullAlways.expected | 1 - csharp/ql/test/query-tests/Nullness/NullMaybe.expected | 3 --- 2 files changed, 4 deletions(-) diff --git a/csharp/ql/test/query-tests/Nullness/NullAlways.expected b/csharp/ql/test/query-tests/Nullness/NullAlways.expected index b52d6e6a4567..ec8a78e817b5 100644 --- a/csharp/ql/test/query-tests/Nullness/NullAlways.expected +++ b/csharp/ql/test/query-tests/Nullness/NullAlways.expected @@ -40,5 +40,4 @@ | E.cs:439:13:439:13 | access to parameter s | Variable $@ is always null at this dereference. | E.cs:435:29:435:29 | s | s | | Forwarding.cs:36:31:36:31 | access to local variable s | Variable $@ is always null at this dereference. | Forwarding.cs:7:16:7:16 | s | s | | Forwarding.cs:40:27:40:27 | access to local variable s | Variable $@ is always null at this dereference. | Forwarding.cs:7:16:7:16 | s | s | -| ImplicitToString.cs:8:23:8:23 | access to local variable o | Variable $@ is always null at this dereference. | ImplicitToString.cs:7:16:7:16 | o | o | | NullAlwaysBad.cs:9:30:9:30 | access to parameter s | Variable $@ is always null at this dereference. | NullAlwaysBad.cs:7:29:7:29 | s | s | diff --git a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected index b1fa7702f8de..631c2cd77660 100644 --- a/csharp/ql/test/query-tests/Nullness/NullMaybe.expected +++ b/csharp/ql/test/query-tests/Nullness/NullMaybe.expected @@ -443,8 +443,6 @@ nodes | GuardedString.cs:34:9:37:40 | if (...) ... | | GuardedString.cs:34:26:34:26 | 0 | | GuardedString.cs:35:31:35:31 | access to local variable s | -| ImplicitToString.cs:7:16:7:23 | SSA def(o) | -| ImplicitToString.cs:8:23:8:23 | access to local variable o | | NullAlwaysBad.cs:7:29:7:29 | SSA param(s) | | NullAlwaysBad.cs:9:30:9:30 | access to parameter s | | NullMaybeBad.cs:7:27:7:27 | access to parameter o | @@ -839,7 +837,6 @@ edges | GuardedString.cs:31:26:31:27 | 10 | GuardedString.cs:34:9:37:40 | if (...) ... | | GuardedString.cs:34:9:37:40 | if (...) ... | GuardedString.cs:34:26:34:26 | 0 | | GuardedString.cs:34:26:34:26 | 0 | GuardedString.cs:35:31:35:31 | access to local variable s | -| ImplicitToString.cs:7:16:7:23 | SSA def(o) | ImplicitToString.cs:8:23:8:23 | access to local variable o | | NullAlwaysBad.cs:7:29:7:29 | SSA param(s) | NullAlwaysBad.cs:9:30:9:30 | access to parameter s | | NullMaybeBad.cs:13:17:13:20 | null | NullMaybeBad.cs:7:27:7:27 | access to parameter o | | Params.cs:20:12:20:15 | null | Params.cs:14:17:14:20 | access to parameter args | From 77f9f4c532bdea6a71ecd3827f5cc29d6c774262 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 13 Jan 2025 10:10:50 +0100 Subject: [PATCH 16/22] C#: Add implicit to string usage in constructor. --- .../VirtualCallInConstructorOrDestructor.cs | 6 ++++++ .../VirtualCallInConstructorOrDestructor.expected | 9 +++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.cs b/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.cs index 95ec516ddbe5..767c4e484a14 100644 --- a/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.cs +++ b/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.cs @@ -47,6 +47,7 @@ class C : B f_nonvirtual(); // GOOD f_interface(); // GOOD ((I)this).f_interface(); // GOOD + var x = $"{this}"; // GOOD // Method access Action a; @@ -70,5 +71,10 @@ class C : B e_sealed += f_nonvirtual; // GOOD e_nonvirtual += f_nonvirtual; // GOOD } + + public override string ToString() + { + return "C"; + } } } diff --git a/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.expected b/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.expected index a2f6281ae4ab..965f33249de1 100644 --- a/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.expected +++ b/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.expected @@ -1,5 +1,6 @@ | VirtualCallInConstructorOrDestructor.cs:45:13:45:23 | call to method f_virtual | Avoid virtual calls in a constructor or destructor. | -| VirtualCallInConstructorOrDestructor.cs:53:17:53:25 | access to method f_virtual | Avoid virtual calls in a constructor or destructor. | -| VirtualCallInConstructorOrDestructor.cs:59:21:59:29 | access to property p_virtual | Avoid virtual calls in a constructor or destructor. | -| VirtualCallInConstructorOrDestructor.cs:64:17:64:23 | access to indexer | Avoid virtual calls in a constructor or destructor. | -| VirtualCallInConstructorOrDestructor.cs:69:13:69:21 | access to event e_virtual | Avoid virtual calls in a constructor or destructor. | +| VirtualCallInConstructorOrDestructor.cs:50:24:50:27 | call to method ToString | Avoid virtual calls in a constructor or destructor. | +| VirtualCallInConstructorOrDestructor.cs:54:17:54:25 | access to method f_virtual | Avoid virtual calls in a constructor or destructor. | +| VirtualCallInConstructorOrDestructor.cs:60:21:60:29 | access to property p_virtual | Avoid virtual calls in a constructor or destructor. | +| VirtualCallInConstructorOrDestructor.cs:65:17:65:23 | access to indexer | Avoid virtual calls in a constructor or destructor. | +| VirtualCallInConstructorOrDestructor.cs:70:13:70:21 | access to event e_virtual | Avoid virtual calls in a constructor or destructor. | From 2bff2d646f2c0d6736313dc1b736352f12da5234 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 13 Jan 2025 10:13:03 +0100 Subject: [PATCH 17/22] C#: Disregards compiler generated virtual calls as problematic virtual calls. --- .../src/Bad Practices/VirtualCallInConstructorOrDestructor.ql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/csharp/ql/src/Bad Practices/VirtualCallInConstructorOrDestructor.ql b/csharp/ql/src/Bad Practices/VirtualCallInConstructorOrDestructor.ql index 24fccf035b40..d754f1a03c59 100644 --- a/csharp/ql/src/Bad Practices/VirtualCallInConstructorOrDestructor.ql +++ b/csharp/ql/src/Bad Practices/VirtualCallInConstructorOrDestructor.ql @@ -34,7 +34,9 @@ predicate overriddenSealed(RefType t, Virtualizable d) { } predicate virtualAccessWithThisQualifier(Expr e, Member d) { - exists(VirtualMethodCall c | c = e and c.getTarget() = d and c.hasThisQualifier()) + exists(VirtualMethodCall c | + c = e and c.getTarget() = d and c.hasThisQualifier() and not c.isImplicit() + ) or exists(VirtualMethodAccess c | c = e and c.getTarget() = d and c.hasThisQualifier()) or From 024de5eafc6d4e43985a7b894b60710ae1670eec Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 13 Jan 2025 10:14:08 +0100 Subject: [PATCH 18/22] C#: Update virtual call in constructor expected test output. --- .../VirtualCallInConstructorOrDestructor.expected | 1 - 1 file changed, 1 deletion(-) diff --git a/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.expected b/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.expected index 965f33249de1..8a97e61bf8cf 100644 --- a/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.expected +++ b/csharp/ql/test/query-tests/Bad Practices/VirtualCallInConstructorOrDestructor/VirtualCallInConstructorOrDestructor.expected @@ -1,5 +1,4 @@ | VirtualCallInConstructorOrDestructor.cs:45:13:45:23 | call to method f_virtual | Avoid virtual calls in a constructor or destructor. | -| VirtualCallInConstructorOrDestructor.cs:50:24:50:27 | call to method ToString | Avoid virtual calls in a constructor or destructor. | | VirtualCallInConstructorOrDestructor.cs:54:17:54:25 | access to method f_virtual | Avoid virtual calls in a constructor or destructor. | | VirtualCallInConstructorOrDestructor.cs:60:21:60:29 | access to property p_virtual | Avoid virtual calls in a constructor or destructor. | | VirtualCallInConstructorOrDestructor.cs:65:17:65:23 | access to indexer | Avoid virtual calls in a constructor or destructor. | From ab70a945e405300da8a26e3cf0bd84897ab3d95b Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Mon, 13 Jan 2025 11:24:24 +0100 Subject: [PATCH 19/22] C#: Add a summary model for PathString.ToString. --- csharp/ql/lib/ext/Microsoft.AspNetCore.Http.model.yml | 6 ++++++ .../library-tests/dataflow/library/FlowSummaries.expected | 1 + .../dataflow/library/FlowSummariesFiltered.expected | 1 + 3 files changed, 8 insertions(+) create mode 100644 csharp/ql/lib/ext/Microsoft.AspNetCore.Http.model.yml diff --git a/csharp/ql/lib/ext/Microsoft.AspNetCore.Http.model.yml b/csharp/ql/lib/ext/Microsoft.AspNetCore.Http.model.yml new file mode 100644 index 000000000000..b4716f100a2e --- /dev/null +++ b/csharp/ql/lib/ext/Microsoft.AspNetCore.Http.model.yml @@ -0,0 +1,6 @@ +extensions: + - addsTo: + pack: codeql/csharp-all + extensible: summaryModel + data: + - ["Microsoft.AspNetCore.Http", "PathString", True, "ToString", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"] diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected index 6c5524bfd2d9..50d4b3562337 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummaries.expected @@ -1258,6 +1258,7 @@ summary | Microsoft.AspNetCore.Http;HttpResponse;OnStarting;(System.Func);Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated | | Microsoft.AspNetCore.Http;IEndpointFilter;InvokeAsync;(Microsoft.AspNetCore.Http.EndpointFilterInvocationContext,Microsoft.AspNetCore.Http.EndpointFilterDelegate);Argument[1];Argument[1].Parameter[delegate-self];value;hq-generated | | Microsoft.AspNetCore.Http;IMiddleware;InvokeAsync;(Microsoft.AspNetCore.Http.HttpContext,Microsoft.AspNetCore.Http.RequestDelegate);Argument[1];Argument[1].Parameter[delegate-self];value;hq-generated | +| Microsoft.AspNetCore.Http;PathString;ToString;();Argument[this];ReturnValue;taint;manual | | Microsoft.AspNetCore.Http;ProblemDetailsOptions;set_CustomizeProblemDetails;(System.Action);Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated | | Microsoft.AspNetCore.Http;QueryCollection+Enumerator;get_Current;();Argument[this];ReturnValue;taint;df-generated | | Microsoft.AspNetCore.Http;QueryCollection;GetEnumerator;();Argument[this].Element;ReturnValue.Property[System.Collections.Generic.IEnumerator`1.Current];value;manual | diff --git a/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected b/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected index f6fe3b940435..f99f76e9273b 100644 --- a/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected +++ b/csharp/ql/test/library-tests/dataflow/library/FlowSummariesFiltered.expected @@ -415,6 +415,7 @@ | Microsoft.AspNetCore.Http;HttpResponse;OnStarting;(System.Func);Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated | | Microsoft.AspNetCore.Http;IEndpointFilter;InvokeAsync;(Microsoft.AspNetCore.Http.EndpointFilterInvocationContext,Microsoft.AspNetCore.Http.EndpointFilterDelegate);Argument[1];Argument[1].Parameter[delegate-self];value;hq-generated | | Microsoft.AspNetCore.Http;IMiddleware;InvokeAsync;(Microsoft.AspNetCore.Http.HttpContext,Microsoft.AspNetCore.Http.RequestDelegate);Argument[1];Argument[1].Parameter[delegate-self];value;hq-generated | +| Microsoft.AspNetCore.Http;PathString;ToString;();Argument[this];ReturnValue;taint;manual | | Microsoft.AspNetCore.Http;ProblemDetailsOptions;set_CustomizeProblemDetails;(System.Action);Argument[0];Argument[0].Parameter[delegate-self];value;hq-generated | | Microsoft.AspNetCore.Http;RequestDelegate;BeginInvoke;(Microsoft.AspNetCore.Http.HttpContext,System.AsyncCallback,System.Object);Argument[1];Argument[1].Parameter[delegate-self];value;hq-generated | | Microsoft.AspNetCore.Http;RequestDelegateFactory;Create;(System.Reflection.MethodInfo,System.Func,Microsoft.AspNetCore.Http.RequestDelegateFactoryOptions);Argument[1];Argument[1].Parameter[delegate-self];value;hq-generated | From 6a406b28d1b8f2e27bfa8cb0d8850a62ffbc591c Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 14 Jan 2025 15:57:21 +0100 Subject: [PATCH 20/22] 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 From 0c5c2a3509b0f06678674d5ae94db42a5e8f8b94 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 14 Jan 2025 15:50:04 +0100 Subject: [PATCH 21/22] C#: Add implicit to string test. --- .../implicittostring/implicitToString.cs | 44 +++++++++++++++++++ .../implicitToString.expected | 4 ++ .../implicittostring/implicitToString.ql | 5 +++ 3 files changed, 53 insertions(+) create mode 100644 csharp/ql/test/library-tests/implicittostring/implicitToString.cs create mode 100644 csharp/ql/test/library-tests/implicittostring/implicitToString.expected create mode 100644 csharp/ql/test/library-tests/implicittostring/implicitToString.ql diff --git a/csharp/ql/test/library-tests/implicittostring/implicitToString.cs b/csharp/ql/test/library-tests/implicittostring/implicitToString.cs new file mode 100644 index 000000000000..d75044246f8e --- /dev/null +++ b/csharp/ql/test/library-tests/implicittostring/implicitToString.cs @@ -0,0 +1,44 @@ +using System; + +public class TestImplicitToString +{ + public class Container + { + public override string ToString() + { + return "Container"; + } + } + + public class FormattableContainer : IFormattable + { + public string ToString(string format, IFormatProvider formatProvider) + { + return "Formatted container"; + } + + + public override string ToString() + { + return "Container"; + } + } + + public void M() + { + var container = new Container(); + + var y = "Hello" + container; // Implicit ToString call + y = "Hello" + container.ToString(); + y = $"Hello {container}"; // Implicit ToString() call + y = $"Hello {container.ToString()}"; + y = $"Hello {container:D}"; // Implicit ToString() call. + + var z = "Hello" + y; // No implicit ToString call as `y` is already a string. + + var formattableContainer = new FormattableContainer(); + y = "Hello" + formattableContainer; // Implicit call to ToString(). + y = $"Hello {formattableContainer}"; // Implicit call to ToString(string, IFormatProvider). We don't handle this. + y = $"Hello {formattableContainer:D}"; // Implicit call to ToString(string, IFormatProvider). We don't handle this. + } +} diff --git a/csharp/ql/test/library-tests/implicittostring/implicitToString.expected b/csharp/ql/test/library-tests/implicittostring/implicitToString.expected new file mode 100644 index 000000000000..4878b12a4fdb --- /dev/null +++ b/csharp/ql/test/library-tests/implicittostring/implicitToString.expected @@ -0,0 +1,4 @@ +| implicitToString.cs:31:27:31:35 | call to method ToString | +| implicitToString.cs:33:22:33:30 | call to method ToString | +| implicitToString.cs:35:22:35:30 | call to method ToString | +| implicitToString.cs:40:23:40:42 | call to method ToString | diff --git a/csharp/ql/test/library-tests/implicittostring/implicitToString.ql b/csharp/ql/test/library-tests/implicittostring/implicitToString.ql new file mode 100644 index 000000000000..4eb518d84c39 --- /dev/null +++ b/csharp/ql/test/library-tests/implicittostring/implicitToString.ql @@ -0,0 +1,5 @@ +import csharp + +from MethodCall c +where c.isImplicit() +select c From 3de5b224c6eed7bb4333c925e867117a180b1b6a Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 15 Jan 2025 09:23:34 +0100 Subject: [PATCH 22/22] C#: Update other existing tests expected output. --- .../controlflow/graph/BasicBlock.expected | 6 +++--- .../controlflow/graph/Dominance.expected | 18 ++++++------------ .../graph/EnclosingCallable.expected | 3 --- .../controlflow/graph/EntryElement.expected | 3 --- .../controlflow/graph/ExitElement.expected | 3 --- .../controlflow/graph/NodeGraph.expected | 9 +++------ .../csharp6/InterpolatedStringExpr.expected | 4 ++-- .../csharp6/MemberAccess.expected | 2 -- .../library-tests/csharp6/PrintAst.expected | 18 ++++++++---------- .../library-tests/csharp7.3/PrintAst.expected | 3 +-- .../test/library-tests/csharp7/IsFlow.expected | 6 ++---- .../csharp7/LocalTaintFlow.expected | 6 +++--- .../library-tests/csharp7/PrintAst.expected | 9 +++------ .../AlternateInterpolatedStrings.expected | 4 ++-- .../library-tests/csharp8/PrintAst.expected | 6 ++---- 15 files changed, 35 insertions(+), 65 deletions(-) diff --git a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected index af76384a3072..527816c645be 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected @@ -859,7 +859,7 @@ | Patterns.cs:5:10:5:11 | enter M1 | Patterns.cs:8:18:8:23 | Int32 i1 | 8 | | Patterns.cs:8:13:8:23 | [false] ... is ... | Patterns.cs:8:13:8:23 | [false] ... is ... | 1 | | Patterns.cs:8:13:8:23 | [true] ... is ... | Patterns.cs:8:13:8:23 | [true] ... is ... | 1 | -| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:42 | call to method WriteLine | 7 | +| Patterns.cs:9:9:11:9 | {...} | Patterns.cs:10:13:10:42 | call to method WriteLine | 6 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:23:12:31 | String s1 | 3 | | Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:12:18:12:31 | [false] ... is ... | 1 | | Patterns.cs:12:18:12:31 | [true] ... is ... | Patterns.cs:12:18:12:31 | [true] ... is ... | 1 | @@ -872,9 +872,9 @@ | Patterns.cs:23:17:23:22 | break; | Patterns.cs:23:17:23:22 | break; | 1 | | Patterns.cs:24:13:24:36 | case ...: | Patterns.cs:24:18:24:23 | Int32 i2 | 2 | | Patterns.cs:24:30:24:31 | access to local variable i2 | Patterns.cs:24:30:24:35 | ... > ... | 3 | -| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:26:17:26:22 | break; | 7 | +| Patterns.cs:25:17:25:52 | ...; | Patterns.cs:26:17:26:22 | break; | 6 | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | 2 | -| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:29:17:29:22 | break; | 7 | +| Patterns.cs:28:17:28:47 | ...; | Patterns.cs:29:17:29:22 | break; | 6 | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | 2 | | Patterns.cs:31:17:31:50 | ...; | Patterns.cs:32:17:32:22 | break; | 6 | | Patterns.cs:33:13:33:24 | case ...: | Patterns.cs:33:18:33:23 | Object v2 | 2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected index 23a62d593d76..9a1a38b7935a 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/Dominance.expected @@ -3147,8 +3147,7 @@ dominance | Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:33:10:36 | "int " | | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:13:10:42 | call to method WriteLine | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:38:10:39 | access to local variable i1 | -| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:38:10:39 | call to method ToString | -| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:10:31:10:41 | $"..." | +| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:31:10:41 | $"..." | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:18 | access to local variable o | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:23:12:31 | String s1 | | Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | @@ -3180,8 +3179,7 @@ dominance | Patterns.cs:25:17:25:52 | ...; | Patterns.cs:25:37:25:45 | "positive " | | Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:17:25:51 | call to method WriteLine | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:47:25:48 | access to local variable i2 | -| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:47:25:48 | call to method ToString | -| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:25:35:25:50 | $"..." | +| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:35:25:50 | $"..." | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:28:17:28:47 | ...; | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:30:13:30:27 | case ...: | @@ -3189,8 +3187,7 @@ dominance | Patterns.cs:28:17:28:47 | ...; | Patterns.cs:28:37:28:40 | "int " | | Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:17:28:46 | call to method WriteLine | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:42:28:43 | access to local variable i3 | -| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:42:28:43 | call to method ToString | -| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:28:35:28:45 | $"..." | +| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:35:28:45 | $"..." | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:31:17:31:50 | ...; | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:33:13:33:24 | case ...: | @@ -7344,10 +7341,9 @@ postDominance | Patterns.cs:9:9:11:9 | {...} | Patterns.cs:8:13:8:23 | [true] ... is ... | | Patterns.cs:10:13:10:42 | call to method WriteLine | Patterns.cs:10:31:10:41 | $"..." | | Patterns.cs:10:13:10:43 | ...; | Patterns.cs:9:9:11:9 | {...} | -| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:38:10:39 | call to method ToString | +| Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:38:10:39 | access to local variable i1 | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:13:10:43 | ...; | | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:33:10:36 | "int " | -| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:10:38:10:39 | access to local variable i1 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:8:13:8:23 | [false] ... is ... | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:14:18:9 | if (...) ... | | Patterns.cs:12:23:12:31 | String s1 | Patterns.cs:12:18:12:18 | access to local variable o | @@ -7372,17 +7368,15 @@ postDominance | Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:24:35:24:35 | 0 | | Patterns.cs:24:35:24:35 | 0 | Patterns.cs:24:30:24:31 | access to local variable i2 | | Patterns.cs:25:17:25:51 | call to method WriteLine | Patterns.cs:25:35:25:50 | $"..." | -| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:47:25:48 | call to method ToString | +| Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:47:25:48 | access to local variable i2 | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:17:25:52 | ...; | | Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:37:25:45 | "positive " | -| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:25:47:25:48 | access to local variable i2 | | Patterns.cs:26:17:26:22 | break; | Patterns.cs:25:17:25:51 | call to method WriteLine | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:27:13:27:24 | case ...: | | Patterns.cs:28:17:28:46 | call to method WriteLine | Patterns.cs:28:35:28:45 | $"..." | -| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:42:28:43 | call to method ToString | +| Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:42:28:43 | access to local variable i3 | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:17:28:47 | ...; | | Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:37:28:40 | "int " | -| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:28:42:28:43 | access to local variable i3 | | Patterns.cs:29:17:29:22 | break; | Patterns.cs:28:17:28:46 | call to method WriteLine | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:30:13:30:27 | case ...: | | Patterns.cs:31:17:31:49 | call to method WriteLine | Patterns.cs:31:35:31:48 | $"..." | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected index e5d4e3c733d4..9edc62925d86 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EnclosingCallable.expected @@ -3437,7 +3437,6 @@ nodeEnclosing | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:5:10:5:11 | M1 | -| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:5:10:5:11 | M1 | @@ -3470,7 +3469,6 @@ nodeEnclosing | Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:5:10:5:11 | M1 | -| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:26:17:26:22 | break; | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:5:10:5:11 | M1 | @@ -3479,7 +3477,6 @@ nodeEnclosing | Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:5:10:5:11 | M1 | -| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:29:17:29:22 | break; | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:5:10:5:11 | M1 | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:5:10:5:11 | M1 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected index 04e93332380c..fddab21f2b62 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/EntryElement.expected @@ -2239,7 +2239,6 @@ | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:33:10:36 | "int " | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:33:10:36 | "int " | | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:38:10:39 | access to local variable i1 | -| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:10:38:10:39 | access to local variable i1 | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:14:18:9 | if (...) ... | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:18:12:18 | access to local variable o | | Patterns.cs:12:18:12:31 | ... is ... | Patterns.cs:12:18:12:18 | access to local variable o | @@ -2270,7 +2269,6 @@ | Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:37:25:45 | "positive " | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:37:25:45 | "positive " | | Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:47:25:48 | access to local variable i2 | -| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:25:47:25:48 | access to local variable i2 | | Patterns.cs:26:17:26:22 | break; | Patterns.cs:26:17:26:22 | break; | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:13:27:24 | case ...: | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:27:18:27:23 | Int32 i3 | @@ -2279,7 +2277,6 @@ | Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:37:28:40 | "int " | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:37:28:40 | "int " | | Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:42:28:43 | access to local variable i3 | -| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:28:42:28:43 | access to local variable i3 | | Patterns.cs:29:17:29:22 | break; | Patterns.cs:29:17:29:22 | break; | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:13:30:27 | case ...: | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:30:18:30:26 | String s2 | diff --git a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected index e8c8a1f75a7f..81ee139f6a68 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/ExitElement.expected @@ -2912,7 +2912,6 @@ | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:31:10:41 | $"..." | normal | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:33:10:36 | "int " | normal | | Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:38:10:39 | access to local variable i1 | normal | -| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:10:38:10:39 | call to method ToString | normal | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:14:13:14:45 | call to method WriteLine | normal | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:16:18:16:28 | ... is ... | false | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:17:9:18:9 | {...} | normal | @@ -2961,7 +2960,6 @@ | Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:35:25:50 | $"..." | normal | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:37:25:45 | "positive " | normal | | Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:47:25:48 | access to local variable i2 | normal | -| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:25:47:25:48 | call to method ToString | normal | | Patterns.cs:26:17:26:22 | break; | Patterns.cs:26:17:26:22 | break; | break | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | no-match | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:28:17:28:46 | call to method WriteLine | normal | @@ -2972,7 +2970,6 @@ | Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:35:28:45 | $"..." | normal | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:37:28:40 | "int " | normal | | Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:42:28:43 | access to local variable i3 | normal | -| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:28:42:28:43 | call to method ToString | normal | | Patterns.cs:29:17:29:22 | break; | Patterns.cs:29:17:29:22 | break; | break | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | no-match | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:31:17:31:49 | call to method WriteLine | normal | diff --git a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected index 53fc61f9bc4f..0078ba76213d 100644 --- a/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected +++ b/csharp/ql/test/library-tests/controlflow/graph/NodeGraph.expected @@ -3528,8 +3528,7 @@ | Patterns.cs:10:13:10:43 | ...; | Patterns.cs:10:33:10:36 | "int " | | | Patterns.cs:10:31:10:41 | $"..." | Patterns.cs:10:13:10:42 | call to method WriteLine | | | Patterns.cs:10:33:10:36 | "int " | Patterns.cs:10:38:10:39 | access to local variable i1 | | -| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:38:10:39 | call to method ToString | | -| Patterns.cs:10:38:10:39 | call to method ToString | Patterns.cs:10:31:10:41 | $"..." | | +| Patterns.cs:10:38:10:39 | access to local variable i1 | Patterns.cs:10:31:10:41 | $"..." | | | Patterns.cs:12:14:18:9 | if (...) ... | Patterns.cs:12:18:12:18 | access to local variable o | | | Patterns.cs:12:18:12:18 | access to local variable o | Patterns.cs:12:23:12:31 | String s1 | | | Patterns.cs:12:18:12:31 | [false] ... is ... | Patterns.cs:16:14:18:9 | if (...) ... | false | @@ -3566,8 +3565,7 @@ | Patterns.cs:25:17:25:52 | ...; | Patterns.cs:25:37:25:45 | "positive " | | | Patterns.cs:25:35:25:50 | $"..." | Patterns.cs:25:17:25:51 | call to method WriteLine | | | Patterns.cs:25:37:25:45 | "positive " | Patterns.cs:25:47:25:48 | access to local variable i2 | | -| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:47:25:48 | call to method ToString | | -| Patterns.cs:25:47:25:48 | call to method ToString | Patterns.cs:25:35:25:50 | $"..." | | +| Patterns.cs:25:47:25:48 | access to local variable i2 | Patterns.cs:25:35:25:50 | $"..." | | | Patterns.cs:26:17:26:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | break | | Patterns.cs:27:13:27:24 | case ...: | Patterns.cs:27:18:27:23 | Int32 i3 | | | Patterns.cs:27:18:27:23 | Int32 i3 | Patterns.cs:28:17:28:47 | ...; | match | @@ -3576,8 +3574,7 @@ | Patterns.cs:28:17:28:47 | ...; | Patterns.cs:28:37:28:40 | "int " | | | Patterns.cs:28:35:28:45 | $"..." | Patterns.cs:28:17:28:46 | call to method WriteLine | | | Patterns.cs:28:37:28:40 | "int " | Patterns.cs:28:42:28:43 | access to local variable i3 | | -| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:42:28:43 | call to method ToString | | -| Patterns.cs:28:42:28:43 | call to method ToString | Patterns.cs:28:35:28:45 | $"..." | | +| Patterns.cs:28:42:28:43 | access to local variable i3 | Patterns.cs:28:35:28:45 | $"..." | | | Patterns.cs:29:17:29:22 | break; | Patterns.cs:40:9:42:9 | switch (...) {...} | break | | Patterns.cs:30:13:30:27 | case ...: | Patterns.cs:30:18:30:26 | String s2 | | | Patterns.cs:30:18:30:26 | String s2 | Patterns.cs:31:17:31:50 | ...; | match | diff --git a/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected b/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected index ce0b425c1137..d10365546bd9 100644 --- a/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected +++ b/csharp/ql/test/library-tests/csharp6/InterpolatedStringExpr.expected @@ -4,11 +4,11 @@ | csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:47:25:52 | ", and " | | csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:54:25:64 | nameof(...) | | csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:66:25:77 | " has length " | -| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:79:25:94 | call to method ToString | +| csharp6.cs:25:23:25:96 | $"..." | csharp6.cs:25:79:25:94 | ... ?? ... | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:20:27:30 | nameof(...) | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:32:27:35 | " is " | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:37:27:39 | access to local variable foo | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:41:27:46 | ", and " | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:48:27:58 | nameof(...) | | csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:60:27:71 | " has length " | -| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:73:27:88 | call to method ToString | +| csharp6.cs:27:16:27:90 | $"..." | csharp6.cs:27:73:27:88 | ... ?? ... | diff --git a/csharp/ql/test/library-tests/csharp6/MemberAccess.expected b/csharp/ql/test/library-tests/csharp6/MemberAccess.expected index c37ea475cbaf..1eda117fadd2 100644 --- a/csharp/ql/test/library-tests/csharp6/MemberAccess.expected +++ b/csharp/ql/test/library-tests/csharp6/MemberAccess.expected @@ -4,8 +4,6 @@ memberAccess | csharp6.cs:32:38:32:70 | access to indexer | csharp6.cs:32:38:32:66 | object creation of type Dictionary | Conditional | | csharp6.cs:32:38:32:73 | access to indexer | csharp6.cs:32:38:32:70 | access to indexer | Unconditional | methodCall -| csharp6.cs:25:79:25:94 | call to method ToString | csharp6.cs:25:79:25:94 | ... ?? ... | Unconditional | -| csharp6.cs:27:73:27:88 | call to method ToString | csharp6.cs:27:73:27:88 | ... ?? ... | Unconditional | | csharp6.cs:30:31:30:44 | call to method ToUpper | csharp6.cs:30:31:30:33 | access to local variable foo | Conditional | extensionMethodCall | csharp6.cs:29:35:29:44 | call to method Any | csharp6.cs:29:35:29:37 | access to local variable bar | Conditional | diff --git a/csharp/ql/test/library-tests/csharp6/PrintAst.expected b/csharp/ql/test/library-tests/csharp6/PrintAst.expected index 2daa487d8a43..892ad6dd4b15 100644 --- a/csharp/ql/test/library-tests/csharp6/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp6/PrintAst.expected @@ -38,11 +38,10 @@ csharp6.cs: # 25| 4: [NameOfExpr] nameof(...) # 25| 0: [LocalVariableAccess] access to local variable bar # 25| 5: [StringLiteralUtf16] " has length " -# 25| 6: [MethodCall] call to method ToString -# 25| -1: [NullCoalescingExpr] ... ?? ... -# 25| 0: [PropertyCall] access to property Length -# 25| -1: [LocalVariableAccess] access to local variable bar -# 25| 1: [IntLiteral] 0 +# 25| 6: [NullCoalescingExpr] ... ?? ... +# 25| 0: [PropertyCall] access to property Length +# 25| -1: [LocalVariableAccess] access to local variable bar +# 25| 1: [IntLiteral] 0 # 27| 2: [ExprStmt] ...; # 27| 0: [MethodCall] call to method Fn # 27| 0: [InterpolatedStringExpr] $"..." @@ -54,11 +53,10 @@ csharp6.cs: # 27| 4: [NameOfExpr] nameof(...) # 27| 0: [LocalVariableAccess] access to local variable bar # 27| 5: [StringLiteralUtf16] " has length " -# 27| 6: [MethodCall] call to method ToString -# 27| -1: [NullCoalescingExpr] ... ?? ... -# 27| 0: [PropertyCall] access to property Length -# 27| -1: [LocalVariableAccess] access to local variable bar -# 27| 1: [IntLiteral] 0 +# 27| 6: [NullCoalescingExpr] ... ?? ... +# 27| 0: [PropertyCall] access to property Length +# 27| -1: [LocalVariableAccess] access to local variable bar +# 27| 1: [IntLiteral] 0 # 29| 3: [LocalVariableDeclStmt] ... ...; # 29| 0: [LocalVariableDeclAndInitExpr] Nullable anythingInBar = ... # 29| -1: [TypeMention] bool? diff --git a/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected b/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected index d693af41f714..d55d5d279ada 100644 --- a/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp7.3/PrintAst.expected @@ -110,5 +110,4 @@ csharp73.cs: # 51| 0: [TypeMention] Console # 51| 0: [InterpolatedStringExpr] $"..." # 51| 0: [StringLiteralUtf16] "x is " -# 51| 1: [MethodCall] call to method ToString -# 51| -1: [LocalVariableAccess] access to local variable x +# 51| 1: [LocalVariableAccess] access to local variable x diff --git a/csharp/ql/test/library-tests/csharp7/IsFlow.expected b/csharp/ql/test/library-tests/csharp7/IsFlow.expected index 1640c8ee678e..b3e283528457 100644 --- a/csharp/ql/test/library-tests/csharp7/IsFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/IsFlow.expected @@ -37,8 +37,7 @@ | CSharp7.cs:258:17:258:52 | ...; | CSharp7.cs:258:37:258:45 | "positive " | semmle.label | successor | | CSharp7.cs:258:35:258:50 | $"..." | CSharp7.cs:258:17:258:51 | call to method WriteLine | semmle.label | successor | | CSharp7.cs:258:37:258:45 | "positive " | CSharp7.cs:258:47:258:48 | access to local variable i2 | semmle.label | successor | -| CSharp7.cs:258:47:258:48 | access to local variable i2 | CSharp7.cs:258:47:258:48 | call to method ToString | semmle.label | successor | -| CSharp7.cs:258:47:258:48 | call to method ToString | CSharp7.cs:258:35:258:50 | $"..." | semmle.label | successor | +| CSharp7.cs:258:47:258:48 | access to local variable i2 | CSharp7.cs:258:35:258:50 | $"..." | semmle.label | successor | | CSharp7.cs:259:17:259:22 | break; | CSharp7.cs:230:10:230:13 | exit Test (normal) | semmle.label | break | | CSharp7.cs:260:13:260:24 | case ...: | CSharp7.cs:260:18:260:23 | Int32 i3 | semmle.label | successor | | CSharp7.cs:260:18:260:23 | Int32 i3 | CSharp7.cs:261:17:261:47 | ...; | semmle.label | match | @@ -47,8 +46,7 @@ | CSharp7.cs:261:17:261:47 | ...; | CSharp7.cs:261:37:261:40 | "int " | semmle.label | successor | | CSharp7.cs:261:35:261:45 | $"..." | CSharp7.cs:261:17:261:46 | call to method WriteLine | semmle.label | successor | | CSharp7.cs:261:37:261:40 | "int " | CSharp7.cs:261:42:261:43 | access to local variable i3 | semmle.label | successor | -| CSharp7.cs:261:42:261:43 | access to local variable i3 | CSharp7.cs:261:42:261:43 | call to method ToString | semmle.label | successor | -| CSharp7.cs:261:42:261:43 | call to method ToString | CSharp7.cs:261:35:261:45 | $"..." | semmle.label | successor | +| CSharp7.cs:261:42:261:43 | access to local variable i3 | CSharp7.cs:261:35:261:45 | $"..." | semmle.label | successor | | CSharp7.cs:262:17:262:22 | break; | CSharp7.cs:230:10:230:13 | exit Test (normal) | semmle.label | break | | CSharp7.cs:263:13:263:27 | case ...: | CSharp7.cs:263:18:263:26 | String s2 | semmle.label | successor | | CSharp7.cs:263:18:263:26 | String s2 | CSharp7.cs:264:17:264:50 | ...; | semmle.label | match | diff --git a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected index d860099ca203..4a16e2491dfe 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalTaintFlow.expected @@ -254,7 +254,7 @@ | CSharp7.cs:233:28:233:33 | ... > ... | CSharp7.cs:233:13:233:33 | [true] ... && ... | | CSharp7.cs:235:13:235:42 | [input] SSA phi read(o) | CSharp7.cs:248:9:274:9 | SSA phi read(o) | | CSharp7.cs:235:33:235:36 | "int " | CSharp7.cs:235:31:235:41 | $"..." | -| CSharp7.cs:235:38:235:39 | call to method ToString | CSharp7.cs:235:31:235:41 | $"..." | +| CSharp7.cs:235:38:235:39 | access to local variable i1 | CSharp7.cs:235:31:235:41 | $"..." | | CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:237:23:237:31 | String s1 | | CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:239:13:239:45 | [input] SSA phi read(o) | | CSharp7.cs:237:18:237:18 | access to local variable o | CSharp7.cs:241:18:241:18 | access to local variable o | @@ -289,11 +289,11 @@ | CSharp7.cs:257:30:257:31 | access to local variable i2 | CSharp7.cs:257:30:257:35 | ... > ... | | CSharp7.cs:257:30:257:31 | access to local variable i2 | CSharp7.cs:258:47:258:48 | access to local variable i2 | | CSharp7.cs:258:37:258:45 | "positive " | CSharp7.cs:258:35:258:50 | $"..." | -| CSharp7.cs:258:47:258:48 | call to method ToString | CSharp7.cs:258:35:258:50 | $"..." | +| CSharp7.cs:258:47:258:48 | access to local variable i2 | CSharp7.cs:258:35:258:50 | $"..." | | CSharp7.cs:260:18:260:23 | Int32 i3 | CSharp7.cs:260:18:260:23 | SSA def(i3) | | CSharp7.cs:260:18:260:23 | SSA def(i3) | CSharp7.cs:261:42:261:43 | access to local variable i3 | | CSharp7.cs:261:37:261:40 | "int " | CSharp7.cs:261:35:261:45 | $"..." | -| CSharp7.cs:261:42:261:43 | call to method ToString | CSharp7.cs:261:35:261:45 | $"..." | +| CSharp7.cs:261:42:261:43 | access to local variable i3 | CSharp7.cs:261:35:261:45 | $"..." | | CSharp7.cs:263:18:263:26 | SSA def(s2) | CSharp7.cs:264:45:264:46 | access to local variable s2 | | CSharp7.cs:263:18:263:26 | String s2 | CSharp7.cs:263:18:263:26 | SSA def(s2) | | CSharp7.cs:264:37:264:43 | "string " | CSharp7.cs:264:35:264:48 | $"..." | diff --git a/csharp/ql/test/library-tests/csharp7/PrintAst.expected b/csharp/ql/test/library-tests/csharp7/PrintAst.expected index dd00d798f44d..e5d009e0df63 100644 --- a/csharp/ql/test/library-tests/csharp7/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp7/PrintAst.expected @@ -727,8 +727,7 @@ CSharp7.cs: # 235| 0: [TypeMention] Console # 235| 0: [InterpolatedStringExpr] $"..." # 235| 0: [StringLiteralUtf16] "int " -# 235| 1: [MethodCall] call to method ToString -# 235| -1: [LocalVariableAccess] access to local variable i1 +# 235| 1: [LocalVariableAccess] access to local variable i1 # 237| 2: [IfStmt] if (...) ... # 237| 0: [IsExpr] ... is ... # 237| 0: [LocalVariableAccess] access to local variable o @@ -790,8 +789,7 @@ CSharp7.cs: # 258| 0: [TypeMention] Console # 258| 0: [InterpolatedStringExpr] $"..." # 258| 0: [StringLiteralUtf16] "positive " -# 258| 1: [MethodCall] call to method ToString -# 258| -1: [LocalVariableAccess] access to local variable i2 +# 258| 1: [LocalVariableAccess] access to local variable i2 # 259| 9: [BreakStmt] break; # 260| 10: [CaseStmt] case ...: # 260| 0: [VariablePatternExpr] Int32 i3 @@ -802,8 +800,7 @@ CSharp7.cs: # 261| 0: [TypeMention] Console # 261| 0: [InterpolatedStringExpr] $"..." # 261| 0: [StringLiteralUtf16] "int " -# 261| 1: [MethodCall] call to method ToString -# 261| -1: [LocalVariableAccess] access to local variable i3 +# 261| 1: [LocalVariableAccess] access to local variable i3 # 262| 12: [BreakStmt] break; # 263| 13: [CaseStmt] case ...: # 263| 0: [VariablePatternExpr] String s2 diff --git a/csharp/ql/test/library-tests/csharp8/AlternateInterpolatedStrings.expected b/csharp/ql/test/library-tests/csharp8/AlternateInterpolatedStrings.expected index 5e065aa35819..06e2f93cbe36 100644 --- a/csharp/ql/test/library-tests/csharp8/AlternateInterpolatedStrings.expected +++ b/csharp/ql/test/library-tests/csharp8/AlternateInterpolatedStrings.expected @@ -1,6 +1,6 @@ inserts -| AlternateInterpolatedStrings.cs:5:17:5:26 | $"..." | 1 | AlternateInterpolatedStrings.cs:5:23:5:24 | call to method ToString | -| AlternateInterpolatedStrings.cs:6:17:6:26 | $"..." | 1 | AlternateInterpolatedStrings.cs:6:23:6:24 | call to method ToString | +| AlternateInterpolatedStrings.cs:5:17:5:26 | $"..." | 1 | AlternateInterpolatedStrings.cs:5:23:5:24 | 12 | +| AlternateInterpolatedStrings.cs:6:17:6:26 | $"..." | 1 | AlternateInterpolatedStrings.cs:6:23:6:24 | 12 | text | AlternateInterpolatedStrings.cs:5:17:5:26 | $"..." | 0 | AlternateInterpolatedStrings.cs:5:20:5:21 | "C:" | | AlternateInterpolatedStrings.cs:6:17:6:26 | $"..." | 0 | AlternateInterpolatedStrings.cs:6:20:6:21 | "C:" | diff --git a/csharp/ql/test/library-tests/csharp8/PrintAst.expected b/csharp/ql/test/library-tests/csharp8/PrintAst.expected index bdf063f624ec..c33374e4761d 100644 --- a/csharp/ql/test/library-tests/csharp8/PrintAst.expected +++ b/csharp/ql/test/library-tests/csharp8/PrintAst.expected @@ -4,14 +4,12 @@ AlternateInterpolatedStrings.cs: # 5| -1: [TypeMention] string # 5| 1: [InterpolatedStringExpr] $"..." # 5| 0: [StringLiteralUtf16] "C:" -# 5| 1: [MethodCall] call to method ToString -# 5| -1: [IntLiteral] 12 +# 5| 1: [IntLiteral] 12 # 6| 6: [Field] s2 # 6| -1: [TypeMention] string # 6| 1: [InterpolatedStringExpr] $"..." # 6| 0: [StringLiteralUtf16] "C:" -# 6| 1: [MethodCall] call to method ToString -# 6| -1: [IntLiteral] 12 +# 6| 1: [IntLiteral] 12 AsyncStreams.cs: # 6| [Class] AsyncStreams # 8| 5: [Method] Items