Skip to content

Commit 0066925

Browse files
committed
C#: Improve CFG for (potential) dynamic accessor calls
1 parent fcad129 commit 0066925

File tree

5 files changed

+61
-24
lines changed

5 files changed

+61
-24
lines changed

csharp/ql/src/semmle/code/csharp/controlflow/ControlFlowGraph.qll

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,9 @@ module ControlFlow {
277277

278278
/** Holds if this node has more than one successor. */
279279
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
280+
281+
/** Gets the enclosing callable of this control flow node. */
282+
Callable getEnclosingCallable() { none() }
280283
}
281284

282285
/** Provides different types of control flow nodes. */
@@ -288,6 +291,8 @@ module ControlFlow {
288291

289292
override BasicBlocks::EntryBlock getBasicBlock() { result = Node.super.getBasicBlock() }
290293

294+
override Callable getEnclosingCallable() { result = this.getCallable() }
295+
291296
override Location getLocation() { result = getCallable().getLocation() }
292297

293298
override string toString() { result = "enter " + getCallable().toString() }
@@ -300,6 +305,8 @@ module ControlFlow {
300305

301306
override BasicBlocks::ExitBlock getBasicBlock() { result = Node.super.getBasicBlock() }
302307

308+
override Callable getEnclosingCallable() { result = this.getCallable() }
309+
303310
override Location getLocation() { result = getCallable().getLocation() }
304311

305312
override string toString() { result = "exit " + getCallable().toString() }
@@ -319,6 +326,8 @@ module ControlFlow {
319326

320327
ElementNode() { this = TElementNode(cfe, splits) }
321328

329+
override Callable getEnclosingCallable() { result = cfe.getEnclosingCallable() }
330+
322331
override ControlFlowElement getElement() { result = cfe }
323332

324333
override string toString() {
@@ -574,6 +583,14 @@ module ControlFlow {
574583
QualifiedWriteAccess() { this.hasQualifier() }
575584
}
576585

586+
/** A normal or a (potential) dynamic call to an accessor. */
587+
private class StatOrDynAccessorCall extends Expr {
588+
StatOrDynAccessorCall() {
589+
this instanceof AccessorCall or
590+
this instanceof DynamicAccess
591+
}
592+
}
593+
577594
/**
578595
* An expression that writes via an accessor call, for example `x.Prop = 0`,
579596
* where `Prop` is a property.
@@ -591,17 +608,17 @@ module ControlFlow {
591608

592609
AccessorWrite() {
593610
def.getExpr() = this and
594-
def.getTargetAccess().(WriteAccess) instanceof AccessorCall and
611+
def.getTargetAccess().(WriteAccess) instanceof StatOrDynAccessorCall and
595612
not this instanceof AssignOperationWithExpandedAssignment
596613
}
597614

598615
/**
599616
* Gets the `i`th accessor being called in this write. More than one call
600617
* can happen in tuple assignments.
601618
*/
602-
AccessorCall getCall(int i) {
619+
StatOrDynAccessorCall getCall(int i) {
603620
result = rank[i + 1](AssignableDefinitions::TupleAssignmentDefinition tdef |
604-
tdef.getExpr() = this and tdef.getTargetAccess() instanceof AccessorCall
621+
tdef.getExpr() = this and tdef.getTargetAccess() instanceof StatOrDynAccessorCall
605622
|
606623
tdef order by tdef.getEvaluationOrder()
607624
).getTargetAccess()

csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
| AccessorCalls.cs:49:10:49:11 | enter M6 | AccessorCalls.cs:49:10:49:11 | exit M6 | 41 |
1111
| AccessorCalls.cs:56:10:56:11 | enter M7 | AccessorCalls.cs:56:10:56:11 | exit M7 | 23 |
1212
| AccessorCalls.cs:61:10:61:11 | enter M8 | AccessorCalls.cs:61:10:61:11 | exit M8 | 29 |
13-
| AccessorCalls.cs:66:10:66:11 | enter M9 | AccessorCalls.cs:66:10:66:11 | exit M9 | 52 |
13+
| AccessorCalls.cs:66:10:66:11 | enter M9 | AccessorCalls.cs:66:10:66:11 | exit M9 | 57 |
1414
| ArrayCreation.cs:3:11:3:12 | enter M1 | ArrayCreation.cs:3:11:3:12 | exit M1 | 4 |
1515
| ArrayCreation.cs:5:12:5:13 | enter M2 | ArrayCreation.cs:5:12:5:13 | exit M2 | 5 |
1616
| ArrayCreation.cs:7:11:7:12 | enter M3 | ArrayCreation.cs:7:11:7:12 | exit M3 | 6 |

csharp/ql/test/library-tests/controlflow/graph/Dominance.expected

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,8 @@
236236
| post | AccessorCalls.cs:68:17:68:21 | dynamic d = ... | AccessorCalls.cs:68:21:68:21 | access to parameter o |
237237
| post | AccessorCalls.cs:68:21:68:21 | access to parameter o | AccessorCalls.cs:68:9:68:22 | ... ...; |
238238
| post | AccessorCalls.cs:69:9:69:9 | access to local variable d | AccessorCalls.cs:69:9:69:36 | ...; |
239-
| post | AccessorCalls.cs:69:9:69:35 | ... = ... | AccessorCalls.cs:69:24:69:35 | dynamic access to member MaybeProp2 |
239+
| post | AccessorCalls.cs:69:9:69:20 | dynamic access to member MaybeProp1 | AccessorCalls.cs:69:24:69:35 | dynamic access to member MaybeProp2 |
240+
| post | AccessorCalls.cs:69:9:69:35 | ... = ... | AccessorCalls.cs:69:9:69:20 | dynamic access to member MaybeProp1 |
240241
| post | AccessorCalls.cs:69:9:69:36 | ...; | AccessorCalls.cs:68:17:68:21 | dynamic d = ... |
241242
| post | AccessorCalls.cs:69:24:69:24 | access to local variable d | AccessorCalls.cs:69:9:69:9 | access to local variable d |
242243
| post | AccessorCalls.cs:69:24:69:35 | dynamic access to member MaybeProp2 | AccessorCalls.cs:69:24:69:24 | access to local variable d |
@@ -247,14 +248,16 @@
247248
| post | AccessorCalls.cs:71:9:71:9 | access to local variable d | AccessorCalls.cs:71:9:71:9 | access to local variable d |
248249
| post | AccessorCalls.cs:71:9:71:9 | access to local variable d | AccessorCalls.cs:71:9:71:26 | ...; |
249250
| post | AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent | AccessorCalls.cs:71:9:71:9 | access to local variable d |
250-
| post | AccessorCalls.cs:71:9:71:25 | ... = ... | AccessorCalls.cs:71:9:71:25 | dynamic call to operator + |
251+
| post | AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent | AccessorCalls.cs:71:9:71:25 | dynamic call to operator + |
252+
| post | AccessorCalls.cs:71:9:71:25 | ... = ... | AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent |
251253
| post | AccessorCalls.cs:71:9:71:25 | dynamic call to operator + | AccessorCalls.cs:71:25:71:25 | access to parameter e |
252254
| post | AccessorCalls.cs:71:9:71:26 | ...; | AccessorCalls.cs:70:9:70:21 | dynamic call to operator ++ |
253255
| post | AccessorCalls.cs:71:25:71:25 | access to parameter e | AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent |
254256
| post | AccessorCalls.cs:72:9:72:9 | access to local variable d | AccessorCalls.cs:72:9:72:21 | ...; |
255257
| post | AccessorCalls.cs:72:9:72:9 | access to local variable d | AccessorCalls.cs:72:11:72:11 | 0 |
258+
| post | AccessorCalls.cs:72:9:72:12 | dynamic access to element | AccessorCalls.cs:72:9:72:20 | dynamic call to operator + |
256259
| post | AccessorCalls.cs:72:9:72:12 | dynamic access to element | AccessorCalls.cs:72:11:72:11 | 0 |
257-
| post | AccessorCalls.cs:72:9:72:20 | ... = ... | AccessorCalls.cs:72:9:72:20 | dynamic call to operator + |
260+
| post | AccessorCalls.cs:72:9:72:20 | ... = ... | AccessorCalls.cs:72:9:72:12 | dynamic access to element |
258261
| post | AccessorCalls.cs:72:9:72:20 | dynamic call to operator + | AccessorCalls.cs:72:17:72:20 | dynamic access to element |
259262
| post | AccessorCalls.cs:72:9:72:21 | ...; | AccessorCalls.cs:71:9:71:25 | ... = ... |
260263
| post | AccessorCalls.cs:72:11:72:11 | 0 | AccessorCalls.cs:72:9:72:9 | access to local variable d |
@@ -263,13 +266,15 @@
263266
| post | AccessorCalls.cs:72:17:72:20 | dynamic access to element | AccessorCalls.cs:72:19:72:19 | 1 |
264267
| post | AccessorCalls.cs:72:19:72:19 | 1 | AccessorCalls.cs:72:17:72:17 | access to local variable d |
265268
| post | AccessorCalls.cs:73:9:73:44 | (..., ...) | AccessorCalls.cs:73:35:73:43 | (..., ...) |
266-
| post | AccessorCalls.cs:73:9:73:83 | ... = ... | AccessorCalls.cs:73:24:73:32 | access to property Prop |
269+
| post | AccessorCalls.cs:73:9:73:83 | ... = ... | AccessorCalls.cs:73:39:73:42 | dynamic access to element |
267270
| post | AccessorCalls.cs:73:9:73:84 | ...; | AccessorCalls.cs:72:9:72:20 | ... = ... |
268271
| post | AccessorCalls.cs:73:10:73:10 | access to local variable d | AccessorCalls.cs:73:9:73:84 | ...; |
272+
| post | AccessorCalls.cs:73:10:73:21 | dynamic access to member MaybeProp1 | AccessorCalls.cs:73:48:73:83 | (..., ...) |
269273
| post | AccessorCalls.cs:73:24:73:27 | this access | AccessorCalls.cs:73:10:73:10 | access to local variable d |
270-
| post | AccessorCalls.cs:73:24:73:32 | access to property Prop | AccessorCalls.cs:73:48:73:83 | (..., ...) |
274+
| post | AccessorCalls.cs:73:24:73:32 | access to property Prop | AccessorCalls.cs:73:10:73:21 | dynamic access to member MaybeProp1 |
271275
| post | AccessorCalls.cs:73:35:73:43 | (..., ...) | AccessorCalls.cs:73:41:73:41 | 0 |
272276
| post | AccessorCalls.cs:73:39:73:39 | access to local variable d | AccessorCalls.cs:73:24:73:27 | this access |
277+
| post | AccessorCalls.cs:73:39:73:42 | dynamic access to element | AccessorCalls.cs:73:24:73:32 | access to property Prop |
273278
| post | AccessorCalls.cs:73:41:73:41 | 0 | AccessorCalls.cs:73:39:73:39 | access to local variable d |
274279
| post | AccessorCalls.cs:73:48:73:83 | (..., ...) | AccessorCalls.cs:73:74:73:82 | (..., ...) |
275280
| post | AccessorCalls.cs:73:49:73:49 | access to local variable d | AccessorCalls.cs:73:9:73:44 | (..., ...) |
@@ -2682,26 +2687,29 @@
26822687
| pre | AccessorCalls.cs:68:17:68:21 | dynamic d = ... | AccessorCalls.cs:69:9:69:36 | ...; |
26832688
| pre | AccessorCalls.cs:68:21:68:21 | access to parameter o | AccessorCalls.cs:68:17:68:21 | dynamic d = ... |
26842689
| pre | AccessorCalls.cs:69:9:69:9 | access to local variable d | AccessorCalls.cs:69:24:69:24 | access to local variable d |
2690+
| pre | AccessorCalls.cs:69:9:69:20 | dynamic access to member MaybeProp1 | AccessorCalls.cs:69:9:69:35 | ... = ... |
26852691
| pre | AccessorCalls.cs:69:9:69:35 | ... = ... | AccessorCalls.cs:70:9:70:22 | ...; |
26862692
| pre | AccessorCalls.cs:69:9:69:36 | ...; | AccessorCalls.cs:69:9:69:9 | access to local variable d |
26872693
| pre | AccessorCalls.cs:69:24:69:24 | access to local variable d | AccessorCalls.cs:69:24:69:35 | dynamic access to member MaybeProp2 |
2688-
| pre | AccessorCalls.cs:69:24:69:35 | dynamic access to member MaybeProp2 | AccessorCalls.cs:69:9:69:35 | ... = ... |
2694+
| pre | AccessorCalls.cs:69:24:69:35 | dynamic access to member MaybeProp2 | AccessorCalls.cs:69:9:69:20 | dynamic access to member MaybeProp1 |
26892695
| pre | AccessorCalls.cs:70:9:70:9 | access to local variable d | AccessorCalls.cs:70:9:70:19 | dynamic access to member MaybeProp |
26902696
| pre | AccessorCalls.cs:70:9:70:19 | dynamic access to member MaybeProp | AccessorCalls.cs:70:9:70:21 | dynamic call to operator ++ |
26912697
| pre | AccessorCalls.cs:70:9:70:21 | dynamic call to operator ++ | AccessorCalls.cs:71:9:71:26 | ...; |
26922698
| pre | AccessorCalls.cs:70:9:70:22 | ...; | AccessorCalls.cs:70:9:70:9 | access to local variable d |
26932699
| pre | AccessorCalls.cs:71:9:71:9 | access to local variable d | AccessorCalls.cs:71:9:71:9 | access to local variable d |
26942700
| pre | AccessorCalls.cs:71:9:71:9 | access to local variable d | AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent |
2701+
| pre | AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent | AccessorCalls.cs:71:9:71:25 | ... = ... |
26952702
| pre | AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent | AccessorCalls.cs:71:25:71:25 | access to parameter e |
26962703
| pre | AccessorCalls.cs:71:9:71:25 | ... = ... | AccessorCalls.cs:72:9:72:21 | ...; |
2697-
| pre | AccessorCalls.cs:71:9:71:25 | dynamic call to operator + | AccessorCalls.cs:71:9:71:25 | ... = ... |
2704+
| pre | AccessorCalls.cs:71:9:71:25 | dynamic call to operator + | AccessorCalls.cs:71:9:71:20 | dynamic access to member MaybeEvent |
26982705
| pre | AccessorCalls.cs:71:9:71:26 | ...; | AccessorCalls.cs:71:9:71:9 | access to local variable d |
26992706
| pre | AccessorCalls.cs:71:25:71:25 | access to parameter e | AccessorCalls.cs:71:9:71:25 | dynamic call to operator + |
27002707
| pre | AccessorCalls.cs:72:9:72:9 | access to local variable d | AccessorCalls.cs:72:11:72:11 | 0 |
27012708
| pre | AccessorCalls.cs:72:9:72:9 | access to local variable d | AccessorCalls.cs:72:11:72:11 | 0 |
2709+
| pre | AccessorCalls.cs:72:9:72:12 | dynamic access to element | AccessorCalls.cs:72:9:72:20 | ... = ... |
27022710
| pre | AccessorCalls.cs:72:9:72:12 | dynamic access to element | AccessorCalls.cs:72:17:72:17 | access to local variable d |
27032711
| pre | AccessorCalls.cs:72:9:72:20 | ... = ... | AccessorCalls.cs:73:9:73:84 | ...; |
2704-
| pre | AccessorCalls.cs:72:9:72:20 | dynamic call to operator + | AccessorCalls.cs:72:9:72:20 | ... = ... |
2712+
| pre | AccessorCalls.cs:72:9:72:20 | dynamic call to operator + | AccessorCalls.cs:72:9:72:12 | dynamic access to element |
27052713
| pre | AccessorCalls.cs:72:9:72:21 | ...; | AccessorCalls.cs:72:9:72:9 | access to local variable d |
27062714
| pre | AccessorCalls.cs:72:11:72:11 | 0 | AccessorCalls.cs:72:9:72:9 | access to local variable d |
27072715
| pre | AccessorCalls.cs:72:11:72:11 | 0 | AccessorCalls.cs:72:9:72:12 | dynamic access to element |
@@ -2712,12 +2720,14 @@
27122720
| pre | AccessorCalls.cs:73:9:73:83 | ... = ... | AccessorCalls.cs:66:10:66:11 | exit M9 |
27132721
| pre | AccessorCalls.cs:73:9:73:84 | ...; | AccessorCalls.cs:73:10:73:10 | access to local variable d |
27142722
| pre | AccessorCalls.cs:73:10:73:10 | access to local variable d | AccessorCalls.cs:73:24:73:27 | this access |
2723+
| pre | AccessorCalls.cs:73:10:73:21 | dynamic access to member MaybeProp1 | AccessorCalls.cs:73:24:73:32 | access to property Prop |
27152724
| pre | AccessorCalls.cs:73:24:73:27 | this access | AccessorCalls.cs:73:39:73:39 | access to local variable d |
2716-
| pre | AccessorCalls.cs:73:24:73:32 | access to property Prop | AccessorCalls.cs:73:9:73:83 | ... = ... |
2725+
| pre | AccessorCalls.cs:73:24:73:32 | access to property Prop | AccessorCalls.cs:73:39:73:42 | dynamic access to element |
27172726
| pre | AccessorCalls.cs:73:35:73:43 | (..., ...) | AccessorCalls.cs:73:9:73:44 | (..., ...) |
27182727
| pre | AccessorCalls.cs:73:39:73:39 | access to local variable d | AccessorCalls.cs:73:41:73:41 | 0 |
2728+
| pre | AccessorCalls.cs:73:39:73:42 | dynamic access to element | AccessorCalls.cs:73:9:73:83 | ... = ... |
27192729
| pre | AccessorCalls.cs:73:41:73:41 | 0 | AccessorCalls.cs:73:35:73:43 | (..., ...) |
2720-
| pre | AccessorCalls.cs:73:48:73:83 | (..., ...) | AccessorCalls.cs:73:24:73:32 | access to property Prop |
2730+
| pre | AccessorCalls.cs:73:48:73:83 | (..., ...) | AccessorCalls.cs:73:10:73:21 | dynamic access to member MaybeProp1 |
27212731
| pre | AccessorCalls.cs:73:49:73:49 | access to local variable d | AccessorCalls.cs:73:49:73:60 | dynamic access to member MaybeProp1 |
27222732
| pre | AccessorCalls.cs:73:49:73:60 | dynamic access to member MaybeProp1 | AccessorCalls.cs:73:63:73:66 | this access |
27232733
| pre | AccessorCalls.cs:73:63:73:66 | this access | AccessorCalls.cs:73:63:73:71 | access to property Prop |

0 commit comments

Comments
 (0)