diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ElementAccess.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ElementAccess.cs
index a5a03ad3fec..d7a0ada9a1d 100644
--- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ElementAccess.cs
+++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/ElementAccess.cs
@@ -79,7 +79,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
///
/// The method symbol to check.
/// True if the method is a slice method; false otherwise.
- private bool IsSliceWithRange(IMethodSymbol method, [NotNullWhen(true)] out RangeExpressionSyntax? range)
+ private bool IsSlice(IMethodSymbol method, out RangeExpressionSyntax? range)
{
range = null;
@@ -89,8 +89,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
}
return (method.Name == "Slice" || method.Name == "Substring")
- && method.Parameters.Length == 2
- && range is not null;
+ && method.Parameters.Length == 2;
}
///
@@ -111,21 +110,31 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
///
/// Even though index expressions can't technically be used in this way, they signal that we
/// could perceive ^b as "length - b".
+ ///
+ /// Call arguments are only populated when a range expression is directly available in
+ /// the list of arguments.
+ /// This means that cases like below are not handled.
+ /// System.Range x = 1..3;
+ /// s[x]
///
/// The trap file to write to.
/// The slice method symbol.
/// The range expression syntax.
- private void PopulateSlice(TextWriter trapFile, IMethodSymbol slice, RangeExpressionSyntax range)
+ private void PopulateSlice(TextWriter trapFile, IMethodSymbol slice, RangeExpressionSyntax? range)
{
- var left = range.LeftOperand is ExpressionSyntax lsyntax
- ? MakeFromRangeEndpoint(lsyntax, this, 0)
- : MakeZeroLiteral(this, 0);
+ if (range is not null)
+ {
+ // Populate the call arguments in case
+ var left = range.LeftOperand is ExpressionSyntax lsyntax
+ ? MakeFromRangeEndpoint(lsyntax, this, 0)
+ : MakeZeroLiteral(this, 0);
- var right = range.RightOperand is ExpressionSyntax rsyntax
- ? MakeFromRangeEndpoint(rsyntax, this, 1)
- : MakeZeroFromEndExpression(this, 1);
+ var right = range.RightOperand is ExpressionSyntax rsyntax
+ ? MakeFromRangeEndpoint(rsyntax, this, 1)
+ : MakeZeroFromEndExpression(this, 1);
- SetExprArgument(trapFile, left, right);
+ SetExprArgument(trapFile, left, right);
+ }
trapFile.expr_call(this, Method.Create(Context, slice));
}
@@ -144,7 +153,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
Create(Context, qualifier, this, -1);
var target = GetTargetSymbol();
- if (target is IMethodSymbol method && IsSliceWithRange(method, out var range))
+ if (target is IMethodSymbol method && IsSlice(method, out var range))
{
// When an indexer on a span or string is used in conjunction with a range expression, the compiler translates
// this into a call to the "Slice" or "Substring" method.