Skip to content

Commit 5080077

Browse files
authored
Merge pull request github#15484 from hvitved/csharp/qualified-delegate-extraction-fix
C#: Fix extraction of qualified delegate calls
2 parents ce4d8d6 + d1ed317 commit 5080077

File tree

5 files changed

+99
-2
lines changed

5 files changed

+99
-2
lines changed

csharp/extractor/Semmle.Extraction.CSharp/Entities/Expressions/Invocation.cs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ private Invocation(ExpressionNodeInfo info)
2020

2121
public static Expression Create(ExpressionNodeInfo info) => new Invocation(info).TryPopulate();
2222

23+
private bool IsEventDelegateCall() => Kind == ExprKind.DELEGATE_INVOCATION && Context.GetModel(Syntax.Expression).GetSymbolInfo(Syntax.Expression).Symbol?.Kind == SymbolKind.Event;
24+
25+
private bool IsExplicitDelegateInvokeCall() => Kind == ExprKind.DELEGATE_INVOCATION && Context.GetModel(Syntax.Expression).GetSymbolInfo(Syntax.Expression).Symbol is IMethodSymbol m && m.MethodKind == MethodKind.DelegateInvoke;
26+
2327
protected override void PopulateExpression(TextWriter trapFile)
2428
{
2529
if (IsNameof(Syntax))
@@ -33,7 +37,7 @@ protected override void PopulateExpression(TextWriter trapFile)
3337
var target = TargetSymbol;
3438
switch (Syntax.Expression)
3539
{
36-
case MemberAccessExpressionSyntax memberAccess:
40+
case MemberAccessExpressionSyntax memberAccess when Kind == ExprKind.METHOD_INVOCATION || IsEventDelegateCall() || IsExplicitDelegateInvokeCall():
3741
memberName = memberAccess.Name.Identifier.Text;
3842
if (Syntax.Expression.Kind() == SyntaxKind.SimpleMemberAccessExpression)
3943
// Qualified method call; `x.M()`
@@ -48,7 +52,7 @@ protected override void PopulateExpression(TextWriter trapFile)
4852
Create(Context, FindConditionalQualifier(memberBinding), this, child++);
4953
MakeConditional(trapFile);
5054
break;
51-
case SimpleNameSyntax simpleName when (Kind == ExprKind.METHOD_INVOCATION):
55+
case SimpleNameSyntax simpleName when Kind == ExprKind.METHOD_INVOCATION:
5256
// Unqualified method call; `M()`
5357
memberName = simpleName.Identifier.Text;
5458
if (target is not null && !target.IsStatic)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
| delegates.cs:72:13:72:20 | delegate call | delegates.cs:72:13:72:15 | access to local variable cd1 |
2+
| delegates.cs:74:13:74:23 | delegate call | delegates.cs:74:13:74:15 | access to local variable cd7 |
3+
| delegates.cs:79:22:79:26 | delegate call | delegates.cs:79:22:79:23 | access to local variable pi |
4+
| delegates.cs:79:30:79:35 | delegate call | delegates.cs:79:30:79:31 | access to local variable ps |
5+
| delegates.cs:95:13:95:25 | delegate call | delegates.cs:95:13:95:22 | access to field Field |
6+
| delegates.cs:96:13:96:28 | delegate call | delegates.cs:96:13:96:25 | access to property Property |
7+
| delegates.cs:97:13:97:20 | delegate call | delegates.cs:97:13:97:17 | access to field Field |
8+
| delegates.cs:98:13:98:23 | delegate call | delegates.cs:98:13:98:20 | access to property Property |
9+
| delegates.cs:99:13:99:28 | function pointer call | delegates.cs:99:13:99:25 | access to field FieldPtr |
10+
| delegates.cs:100:13:100:31 | function pointer call | delegates.cs:100:13:100:28 | access to property PropertyPtr |
11+
| delegates.cs:101:13:101:23 | function pointer call | delegates.cs:101:13:101:20 | access to field FieldPtr |
12+
| delegates.cs:102:13:102:26 | function pointer call | delegates.cs:102:13:102:23 | access to property PropertyPtr |
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import csharp
2+
3+
from DelegateLikeCall dc
4+
select dc, dc.getExpr()

csharp/ql/test/library-tests/delegates/PrintAst.expected

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,3 +249,61 @@ delegates.cs:
249249
# 81| 16: [LocalVariableDeclStmt] ... ...;
250250
# 81| 0: [LocalVariableDeclExpr] ContextCallback d
251251
# 81| 0: [TypeMention] ContextCallback
252+
# 86| 10: [Class] E
253+
# 88| 5: [Field] Field
254+
# 88| -1: [TypeMention] Action<int>
255+
# 88| 1: [TypeMention] int
256+
# 89| 6: [Property] Property
257+
# 89| -1: [TypeMention] Action<int>
258+
# 89| 1: [TypeMention] int
259+
# 89| 3: [Getter] get_Property
260+
# 89| 4: [Setter] set_Property
261+
#-----| 2: (Parameters)
262+
# 89| 0: [Parameter] value
263+
# 90| 7: [Field] FieldPtr
264+
# 90| -1: [TypeMention] delegate* default<Int32,Void>
265+
# 91| 8: [Property] PropertyPtr
266+
# 91| -1: [TypeMention] delegate* default<Int32,Void>
267+
# 91| 3: [Getter] get_PropertyPtr
268+
# 91| 4: [Setter] set_PropertyPtr
269+
#-----| 2: (Parameters)
270+
# 91| 0: [Parameter] value
271+
# 93| 9: [Method] M
272+
# 93| -1: [TypeMention] Void
273+
# 94| 4: [BlockStmt] {...}
274+
# 95| 0: [ExprStmt] ...;
275+
# 95| 0: [DelegateCall] delegate call
276+
# 95| -1: [FieldAccess] access to field Field
277+
# 95| -1: [ThisAccess] this access
278+
# 95| 0: [IntLiteral] 0
279+
# 96| 1: [ExprStmt] ...;
280+
# 96| 0: [DelegateCall] delegate call
281+
# 96| -1: [PropertyCall] access to property Property
282+
# 96| -1: [ThisAccess] this access
283+
# 96| 0: [IntLiteral] 0
284+
# 97| 2: [ExprStmt] ...;
285+
# 97| 0: [DelegateCall] delegate call
286+
# 97| -1: [FieldAccess] access to field Field
287+
# 97| 0: [IntLiteral] 0
288+
# 98| 3: [ExprStmt] ...;
289+
# 98| 0: [DelegateCall] delegate call
290+
# 98| -1: [PropertyCall] access to property Property
291+
# 98| 0: [IntLiteral] 0
292+
# 99| 4: [ExprStmt] ...;
293+
# 99| 0: [FunctionPointerCall] function pointer call
294+
# 99| -1: [FieldAccess] access to field FieldPtr
295+
# 99| -1: [ThisAccess] this access
296+
# 99| 0: [IntLiteral] 0
297+
# 100| 5: [ExprStmt] ...;
298+
# 100| 0: [FunctionPointerCall] function pointer call
299+
# 100| -1: [PropertyCall] access to property PropertyPtr
300+
# 100| -1: [ThisAccess] this access
301+
# 100| 0: [IntLiteral] 0
302+
# 101| 6: [ExprStmt] ...;
303+
# 101| 0: [FunctionPointerCall] function pointer call
304+
# 101| -1: [FieldAccess] access to field FieldPtr
305+
# 101| 0: [IntLiteral] 0
306+
# 102| 7: [ExprStmt] ...;
307+
# 102| 0: [FunctionPointerCall] function pointer call
308+
# 102| -1: [PropertyCall] access to property PropertyPtr
309+
# 102| 0: [IntLiteral] 0

csharp/ql/test/library-tests/delegates/delegates.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,4 +83,23 @@ static void Main()
8383

8484
}
8585

86+
unsafe class E
87+
{
88+
Action<int> Field;
89+
Action<int> Property { get; set; }
90+
delegate*<int, void> FieldPtr;
91+
delegate*<int, void> PropertyPtr { get; set; }
92+
93+
unsafe void M()
94+
{
95+
this.Field(0);
96+
this.Property(0);
97+
Field(0);
98+
Property(0);
99+
this.FieldPtr(0);
100+
this.PropertyPtr(0);
101+
FieldPtr(0);
102+
PropertyPtr(0);
103+
}
104+
}
86105
}

0 commit comments

Comments
 (0)