Skip to content

Commit 9031e19

Browse files
committed
C#: Recognize ref assignments through delegate calls
1 parent fc5076b commit 9031e19

File tree

4 files changed

+17
-12
lines changed

4 files changed

+17
-12
lines changed

csharp/ql/src/semmle/code/csharp/Assignable.qll

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,9 +162,8 @@ module AssignableInternal {
162162
* Holds if the `ref` assignment to `aa` via call `c` is relevant.
163163
*/
164164
private predicate isRelevantRefCall(Call c, AssignableAccess aa) {
165-
c.getAnArgument() = aa and
166-
aa.isRefArgument() and
167-
(isNonAnalyzableRefCall(c, aa, _) or exists(getAnAnalyzableRefDef(c, aa, _)))
165+
isNonAnalyzableRefCall(c, aa) or
166+
exists(getAnAnalyzableRefDef(c, aa, _))
168167
}
169168

170169
private Callable getRefCallTarget(Call c, AssignableAccess aa, Parameter p) {
@@ -220,10 +219,16 @@ module AssignableInternal {
220219
* Equivalent with `not isAnalyzableRefCall(mc, aa, p)`, but avoids negative
221220
* recursion.
222221
*/
223-
private predicate isNonAnalyzableRefCall(Call c, AssignableAccess aa, Parameter p) {
224-
exists(Callable callable | callable = getRefCallTarget(c, aa, p) |
225-
callable.(Virtualizable).isOverridableOrImplementable() or
226-
not callable.hasBody()
222+
private predicate isNonAnalyzableRefCall(Call c, AssignableAccess aa) {
223+
aa = c.getAnArgument() and
224+
aa.isRefArgument() and
225+
(
226+
not exists(getRefCallTarget(c, aa, _))
227+
or
228+
exists(Callable callable | callable = getRefCallTarget(c, aa, _) |
229+
callable.(Virtualizable).isOverridableOrImplementable() or
230+
not callable.hasBody()
231+
)
227232
)
228233
}
229234

@@ -275,7 +280,8 @@ module AssignableInternal {
275280
not lvde.hasInitializer() and
276281
not exists(getTupleSource(TTupleAssignmentDefinition(_, lvde))) and
277282
not lvde = any(IsPatternExpr ipe).getVariableDeclExpr() and
278-
not lvde = any(TypeCase tc).getVariableDeclExpr()
283+
not lvde = any(TypeCase tc).getVariableDeclExpr() and
284+
not lvde.isOutArgument()
279285
} or
280286
TImplicitParameterDefinition(Parameter p) {
281287
exists(Callable c | p = c.getAParameter() |

csharp/ql/test/library-tests/assignables/AssignableAccess.expected

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@
9292
| Assignables.cs:123:13:123:13 | access to local variable x | Assignables.cs:123:13:123:13 | x | write |
9393
| Assignables.cs:124:9:124:9 | access to parameter d | Assignables.cs:121:31:121:31 | d | read |
9494
| Assignables.cs:124:15:124:15 | access to local variable x | Assignables.cs:123:13:123:13 | x | read |
95+
| Assignables.cs:124:15:124:15 | access to local variable x | Assignables.cs:123:13:123:13 | x | write |
9596
| Assignables.cs:124:29:124:29 | String s | Assignables.cs:124:29:124:29 | s | write |
9697
| Discards.cs:7:9:7:9 | access to parameter x | Discards.cs:5:30:5:30 | x | write |
9798
| Discards.cs:20:32:20:32 | Boolean z | Discards.cs:20:32:20:32 | z | write |

csharp/ql/test/library-tests/assignables/AssignableDefinition.expected

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,14 @@
8080
| Assignables.cs:116:13:116:13 | s | Assignables.cs:117:9:117:30 | ... = ... | Assignables.cs:117:9:117:9 | access to local variable s | Assignables.cs:117:13:117:30 | nameof(...) | certain |
8181
| Assignables.cs:121:31:121:31 | d | Assignables.cs:121:31:121:31 | d | Assignables.cs:121:31:121:31 | <none> | Assignables.cs:121:31:121:31 | <none> | certain |
8282
| Assignables.cs:123:13:123:13 | x | Assignables.cs:123:13:123:17 | Int32 x = ... | Assignables.cs:123:13:123:13 | access to local variable x | Assignables.cs:123:17:123:17 | 0 | certain |
83-
| Assignables.cs:124:29:124:29 | s | Assignables.cs:124:29:124:29 | String s | Assignables.cs:124:29:124:29 | <none> | Assignables.cs:124:29:124:29 | <none> | certain |
83+
| Assignables.cs:123:13:123:13 | x | Assignables.cs:124:15:124:15 | access to local variable x | Assignables.cs:124:15:124:15 | access to local variable x | Assignables.cs:124:15:124:15 | <none> | certain |
8484
| Assignables.cs:124:29:124:29 | s | Assignables.cs:124:29:124:29 | String s | Assignables.cs:124:29:124:29 | String s | Assignables.cs:124:29:124:29 | <none> | certain |
8585
| Discards.cs:5:30:5:30 | x | Discards.cs:5:30:5:30 | x | Discards.cs:5:30:5:30 | <none> | Discards.cs:5:30:5:30 | <none> | certain |
8686
| Discards.cs:5:30:5:30 | x | Discards.cs:7:9:7:17 | ... = ... | Discards.cs:7:9:7:9 | access to parameter x | Discards.cs:7:13:7:17 | false | certain |
8787
| Discards.cs:19:14:19:14 | x | Discards.cs:19:9:19:29 | ... = ... | Discards.cs:19:9:19:29 | <none> | Discards.cs:19:9:19:29 | <none> | certain |
8888
| Discards.cs:19:14:19:14 | x | Discards.cs:19:14:19:14 | Int32 x | Discards.cs:19:14:19:14 | <none> | Discards.cs:19:14:19:14 | <none> | certain |
8989
| Discards.cs:20:17:20:17 | y | Discards.cs:20:9:20:33 | ... = ... | Discards.cs:20:9:20:33 | <none> | Discards.cs:20:9:20:33 | <none> | certain |
9090
| Discards.cs:20:17:20:17 | y | Discards.cs:20:17:20:17 | Double y | Discards.cs:20:17:20:17 | <none> | Discards.cs:20:17:20:17 | <none> | certain |
91-
| Discards.cs:20:32:20:32 | z | Discards.cs:20:32:20:32 | Boolean z | Discards.cs:20:32:20:32 | <none> | Discards.cs:20:32:20:32 | <none> | certain |
9291
| Discards.cs:20:32:20:32 | z | Discards.cs:20:32:20:32 | Boolean z | Discards.cs:20:32:20:32 | Boolean z | Discards.cs:20:32:20:32 | <none> | certain |
9392
| Discards.cs:23:27:23:30 | args | Discards.cs:23:27:23:30 | args | Discards.cs:23:27:23:30 | <none> | Discards.cs:23:27:23:30 | <none> | certain |
9493
| Discards.cs:30:24:30:24 | o | Discards.cs:30:24:30:24 | o | Discards.cs:30:24:30:24 | <none> | Discards.cs:30:24:30:24 | <none> | certain |

csharp/ql/test/library-tests/assignables/AssignableDefinitionNode.expected

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,8 @@
7979
| Assignables.cs:117:9:117:30 | ... = ... | Assignables.cs:117:9:117:30 | ... = ... |
8080
| Assignables.cs:121:31:121:31 | d | Assignables.cs:121:10:121:20 | enter DelegateRef |
8181
| Assignables.cs:123:13:123:17 | Int32 x = ... | Assignables.cs:123:13:123:17 | Int32 x = ... |
82+
| Assignables.cs:124:15:124:15 | access to local variable x | Assignables.cs:124:9:124:30 | delegate call |
8283
| Assignables.cs:124:29:124:29 | String s | Assignables.cs:124:9:124:30 | delegate call |
83-
| Assignables.cs:124:29:124:29 | String s | Assignables.cs:124:29:124:29 | String s |
8484
| Discards.cs:5:30:5:30 | x | Discards.cs:5:19:5:19 | enter f |
8585
| Discards.cs:7:9:7:17 | ... = ... | Discards.cs:7:9:7:17 | ... = ... |
8686
| Discards.cs:13:9:13:20 | ... = ... | Discards.cs:13:9:13:20 | ... = ... |
@@ -93,7 +93,6 @@
9393
| Discards.cs:20:9:20:33 | ... = ... | Discards.cs:20:9:20:33 | ... = ... |
9494
| Discards.cs:20:17:20:17 | Double y | Discards.cs:20:17:20:17 | Double y |
9595
| Discards.cs:20:32:20:32 | Boolean z | Discards.cs:20:22:20:33 | call to method f |
96-
| Discards.cs:20:32:20:32 | Boolean z | Discards.cs:20:32:20:32 | Boolean z |
9796
| Discards.cs:23:27:23:30 | args | Discards.cs:23:10:23:16 | enter Foreach |
9897
| Discards.cs:30:24:30:24 | o | Discards.cs:30:10:30:15 | enter Switch |
9998
| Finally.cs:5:16:5:16 | b | Finally.cs:5:9:5:9 | enter M |

0 commit comments

Comments
 (0)