Skip to content

Commit 275822f

Browse files
authored
Merge pull request github#15296 from michaelnebel/csharp/getruntimeargument
C#: Improve getRuntimeArgumentForParameter to consider named arguments.
2 parents 9becd08 + dcce93a commit 275822f

File tree

6 files changed

+75
-20
lines changed

6 files changed

+75
-20
lines changed

csharp/ql/lib/semmle/code/csharp/exprs/Call.qll

Lines changed: 33 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -60,18 +60,17 @@ class Call extends DotNet::Call, Expr, @call {
6060
*/
6161
cached
6262
override Expr getArgumentForParameter(DotNet::Parameter p) {
63+
// Appears in the positional part of the call
64+
result = this.getImplicitArgument(p)
65+
or
66+
// Appears in the named part of the call
6367
this.getTarget().getAParameter() = p and
64-
(
65-
// Appears in the positional part of the call
66-
result = this.getImplicitArgument(p)
67-
or
68-
// Appears in the named part of the call
69-
result = this.getExplicitArgument(p.getName())
70-
)
68+
result = this.getExplicitArgument(p.getName())
7169
}
7270

7371
pragma[noinline]
7472
private Expr getImplicitArgument(DotNet::Parameter p) {
73+
this.getTarget().getAParameter() = p and
7574
not exists(result.getExplicitArgumentName()) and
7675
(
7776
p.(Parameter).isParams() and
@@ -183,24 +182,38 @@ class Call extends DotNet::Call, Expr, @call {
183182
* Gets the argument that corresponds to parameter `p` of a potential
184183
* run-time target of this call.
185184
*
186-
* Does not consider
187-
* - default arguments,
188-
* - named arguments.
185+
* This takes into account both positional and named arguments, but does not
186+
* consider default arguments.
189187
*/
188+
cached
190189
Expr getRuntimeArgumentForParameter(Parameter p) {
191-
exists(Callable c |
192-
c = this.getARuntimeTarget() and
193-
p = c.getAParameter() and
194-
(
195-
p.isParams() and
196-
result = this.getRuntimeArgument(any(int i | i >= p.getPosition()))
197-
or
198-
not p.isParams() and
199-
result = this.getRuntimeArgument(p.getPosition())
200-
)
190+
// Appears in the positional part of the call
191+
result = this.getImplicitRuntimeArgument(p)
192+
or
193+
// Appears in the named part of the call
194+
this.getARuntimeTarget().getAParameter() = p and
195+
result = this.getExplicitRuntimeArgument(p.getName())
196+
}
197+
198+
pragma[noinline]
199+
private Expr getImplicitRuntimeArgument(Parameter p) {
200+
this.getARuntimeTarget().getAParameter() = p and
201+
not exists(result.getExplicitArgumentName()) and
202+
(
203+
p.isParams() and
204+
result = this.getRuntimeArgument(any(int i | i >= p.getPosition()))
205+
or
206+
not p.isParams() and
207+
result = this.getRuntimeArgument(p.getPosition())
201208
)
202209
}
203210

211+
pragma[nomagic]
212+
private Expr getExplicitRuntimeArgument(string name) {
213+
result = this.getARuntimeArgument() and
214+
result.getExplicitArgumentName() = name
215+
}
216+
204217
/**
205218
* Gets the argument that corresponds to a parameter named `name` of a potential
206219
* run-time target of this call.

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

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,3 +421,30 @@ lambdas.cs:
421421
# 17| 0: [IntLiteral] 7
422422
# 17| 1: [IntLiteral] 8
423423
# 17| 2: [IntLiteral] 9
424+
# 20| 6: [DelegateType] MyDelegate
425+
#-----| 2: (Parameters)
426+
# 20| 0: [Parameter] x
427+
# 20| -1: [TypeMention] int
428+
# 20| 1: [Parameter] y
429+
# 20| -1: [TypeMention] int
430+
# 22| 7: [Method] M2
431+
# 22| -1: [TypeMention] Void
432+
# 23| 4: [BlockStmt] {...}
433+
# 24| 0: [LocalVariableDeclStmt] ... ...;
434+
# 24| 0: [LocalVariableDeclAndInitExpr] MyDelegate sum = ...
435+
# 24| -1: [TypeMention] MyDelegate
436+
# 24| 0: [LocalVariableAccess] access to local variable sum
437+
# 24| 1: [LambdaExpr] (...) => ...
438+
#-----| 2: (Parameters)
439+
# 24| 0: [Parameter] x
440+
# 24| -1: [TypeMention] int
441+
# 24| 1: [Parameter] y
442+
# 24| -1: [TypeMention] int
443+
# 24| 4: [AddExpr] ... + ...
444+
# 24| 0: [ParameterAccess] access to parameter x
445+
# 24| 1: [ParameterAccess] access to parameter y
446+
# 25| 1: [ExprStmt] ...;
447+
# 25| 0: [DelegateCall] delegate call
448+
# 25| -1: [LocalVariableAccess] access to local variable sum
449+
# 25| 0: [IntLiteral] 4
450+
# 25| 1: [IntLiteral] 5

csharp/ql/test/library-tests/arguments/argumentName.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,3 +11,5 @@
1111
| arguments.cs:70:36:70:36 | 0 | x |
1212
| arguments.cs:78:18:78:21 | access to parameter args | args |
1313
| arguments.cs:78:27:78:27 | 0 | o |
14+
| lambdas.cs:25:16:25:16 | 4 | y |
15+
| lambdas.cs:25:22:25:22 | 5 | x |

csharp/ql/test/library-tests/arguments/argumentType.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,3 +79,5 @@
7979
| lambdas.cs:17:12:17:12 | 7 | 0 |
8080
| lambdas.cs:17:15:17:15 | 8 | 0 |
8181
| lambdas.cs:17:18:17:18 | 9 | 0 |
82+
| lambdas.cs:25:16:25:16 | 4 | 0 |
83+
| lambdas.cs:25:22:25:22 | 5 | 0 |

csharp/ql/test/library-tests/arguments/lambdaArgument.expected

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@
77
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:12:17:12 | 7 |
88
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:15:17:15 | 8 |
99
| lambdas.cs:17:9:17:19 | delegate call | lambdas.cs:15:32:15:32 | x | lambdas.cs:17:18:17:18 | 9 |
10+
| lambdas.cs:25:9:25:23 | delegate call | lambdas.cs:24:31:24:31 | x | lambdas.cs:25:22:25:22 | 5 |
11+
| lambdas.cs:25:9:25:23 | delegate call | lambdas.cs:24:38:24:38 | y | lambdas.cs:25:16:25:16 | 4 |

csharp/ql/test/library-tests/arguments/lambdas.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,13 @@ void M1()
1616
l3();
1717
l3(7, 8, 9);
1818
}
19+
20+
delegate int MyDelegate(int x, int y);
21+
22+
void M2()
23+
{
24+
MyDelegate sum = (int x, int y) => x + y;
25+
sum(y: 4, x: 5);
26+
}
1927
}
28+

0 commit comments

Comments
 (0)