Merge pull request #15484 from hvitved/csharp/qualified-delegate-extraction-fix

C#: Fix extraction of qualified delegate calls
This commit is contained in:
Tom Hvitved
2024-02-01 11:50:09 +01:00
committed by GitHub
5 changed files with 99 additions and 2 deletions

View File

@@ -20,6 +20,10 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
public static Expression Create(ExpressionNodeInfo info) => new Invocation(info).TryPopulate();
private bool IsEventDelegateCall() => Kind == ExprKind.DELEGATE_INVOCATION && Context.GetModel(Syntax.Expression).GetSymbolInfo(Syntax.Expression).Symbol?.Kind == SymbolKind.Event;
private bool IsExplicitDelegateInvokeCall() => Kind == ExprKind.DELEGATE_INVOCATION && Context.GetModel(Syntax.Expression).GetSymbolInfo(Syntax.Expression).Symbol is IMethodSymbol m && m.MethodKind == MethodKind.DelegateInvoke;
protected override void PopulateExpression(TextWriter trapFile)
{
if (IsNameof(Syntax))
@@ -33,7 +37,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
var target = TargetSymbol;
switch (Syntax.Expression)
{
case MemberAccessExpressionSyntax memberAccess:
case MemberAccessExpressionSyntax memberAccess when Kind == ExprKind.METHOD_INVOCATION || IsEventDelegateCall() || IsExplicitDelegateInvokeCall():
memberName = memberAccess.Name.Identifier.Text;
if (Syntax.Expression.Kind() == SyntaxKind.SimpleMemberAccessExpression)
// Qualified method call; `x.M()`
@@ -48,7 +52,7 @@ namespace Semmle.Extraction.CSharp.Entities.Expressions
Create(Context, FindConditionalQualifier(memberBinding), this, child++);
MakeConditional(trapFile);
break;
case SimpleNameSyntax simpleName when (Kind == ExprKind.METHOD_INVOCATION):
case SimpleNameSyntax simpleName when Kind == ExprKind.METHOD_INVOCATION:
// Unqualified method call; `M()`
memberName = simpleName.Identifier.Text;
if (target is not null && !target.IsStatic)

View File

@@ -0,0 +1,12 @@
| delegates.cs:72:13:72:20 | delegate call | delegates.cs:72:13:72:15 | access to local variable cd1 |
| delegates.cs:74:13:74:23 | delegate call | delegates.cs:74:13:74:15 | access to local variable cd7 |
| delegates.cs:79:22:79:26 | delegate call | delegates.cs:79:22:79:23 | access to local variable pi |
| delegates.cs:79:30:79:35 | delegate call | delegates.cs:79:30:79:31 | access to local variable ps |
| delegates.cs:95:13:95:25 | delegate call | delegates.cs:95:13:95:22 | access to field Field |
| delegates.cs:96:13:96:28 | delegate call | delegates.cs:96:13:96:25 | access to property Property |
| delegates.cs:97:13:97:20 | delegate call | delegates.cs:97:13:97:17 | access to field Field |
| delegates.cs:98:13:98:23 | delegate call | delegates.cs:98:13:98:20 | access to property Property |
| delegates.cs:99:13:99:28 | function pointer call | delegates.cs:99:13:99:25 | access to field FieldPtr |
| delegates.cs:100:13:100:31 | function pointer call | delegates.cs:100:13:100:28 | access to property PropertyPtr |
| delegates.cs:101:13:101:23 | function pointer call | delegates.cs:101:13:101:20 | access to field FieldPtr |
| delegates.cs:102:13:102:26 | function pointer call | delegates.cs:102:13:102:23 | access to property PropertyPtr |

View File

@@ -0,0 +1,4 @@
import csharp
from DelegateLikeCall dc
select dc, dc.getExpr()

View File

@@ -249,3 +249,61 @@ delegates.cs:
# 81| 16: [LocalVariableDeclStmt] ... ...;
# 81| 0: [LocalVariableDeclExpr] ContextCallback d
# 81| 0: [TypeMention] ContextCallback
# 86| 10: [Class] E
# 88| 5: [Field] Field
# 88| -1: [TypeMention] Action<int>
# 88| 1: [TypeMention] int
# 89| 6: [Property] Property
# 89| -1: [TypeMention] Action<int>
# 89| 1: [TypeMention] int
# 89| 3: [Getter] get_Property
# 89| 4: [Setter] set_Property
#-----| 2: (Parameters)
# 89| 0: [Parameter] value
# 90| 7: [Field] FieldPtr
# 90| -1: [TypeMention] delegate* default<Int32,Void>
# 91| 8: [Property] PropertyPtr
# 91| -1: [TypeMention] delegate* default<Int32,Void>
# 91| 3: [Getter] get_PropertyPtr
# 91| 4: [Setter] set_PropertyPtr
#-----| 2: (Parameters)
# 91| 0: [Parameter] value
# 93| 9: [Method] M
# 93| -1: [TypeMention] Void
# 94| 4: [BlockStmt] {...}
# 95| 0: [ExprStmt] ...;
# 95| 0: [DelegateCall] delegate call
# 95| -1: [FieldAccess] access to field Field
# 95| -1: [ThisAccess] this access
# 95| 0: [IntLiteral] 0
# 96| 1: [ExprStmt] ...;
# 96| 0: [DelegateCall] delegate call
# 96| -1: [PropertyCall] access to property Property
# 96| -1: [ThisAccess] this access
# 96| 0: [IntLiteral] 0
# 97| 2: [ExprStmt] ...;
# 97| 0: [DelegateCall] delegate call
# 97| -1: [FieldAccess] access to field Field
# 97| 0: [IntLiteral] 0
# 98| 3: [ExprStmt] ...;
# 98| 0: [DelegateCall] delegate call
# 98| -1: [PropertyCall] access to property Property
# 98| 0: [IntLiteral] 0
# 99| 4: [ExprStmt] ...;
# 99| 0: [FunctionPointerCall] function pointer call
# 99| -1: [FieldAccess] access to field FieldPtr
# 99| -1: [ThisAccess] this access
# 99| 0: [IntLiteral] 0
# 100| 5: [ExprStmt] ...;
# 100| 0: [FunctionPointerCall] function pointer call
# 100| -1: [PropertyCall] access to property PropertyPtr
# 100| -1: [ThisAccess] this access
# 100| 0: [IntLiteral] 0
# 101| 6: [ExprStmt] ...;
# 101| 0: [FunctionPointerCall] function pointer call
# 101| -1: [FieldAccess] access to field FieldPtr
# 101| 0: [IntLiteral] 0
# 102| 7: [ExprStmt] ...;
# 102| 0: [FunctionPointerCall] function pointer call
# 102| -1: [PropertyCall] access to property PropertyPtr
# 102| 0: [IntLiteral] 0

View File

@@ -83,4 +83,23 @@ namespace Delegates
}
unsafe class E
{
Action<int> Field;
Action<int> Property { get; set; }
delegate*<int, void> FieldPtr;
delegate*<int, void> PropertyPtr { get; set; }
unsafe void M()
{
this.Field(0);
this.Property(0);
Field(0);
Property(0);
this.FieldPtr(0);
this.PropertyPtr(0);
FieldPtr(0);
PropertyPtr(0);
}
}
}