Skip to content

Commit 621d845

Browse files
authored
Merge pull request #11 from calumgrant/cs/standalone-cfg-fixes
C#: Fix CFG for unknown expressions
2 parents 35a83bf + ecb3efb commit 621d845

File tree

4 files changed

+59
-0
lines changed

4 files changed

+59
-0
lines changed

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -950,6 +950,7 @@ module ControlFlow {
950950
not this instanceof CastExpr and
951951
not this instanceof AnonymousFunctionExpr and
952952
not this instanceof DelegateCall and
953+
not this instanceof @unknown_expr and
953954
result = this.getChild(i)
954955
or
955956
this = any(ExtensionMethodCall emc |
@@ -967,6 +968,8 @@ module ControlFlow {
967968
result = getCastExprChild(this, i)
968969
or
969970
result = this.(DelegateCall).getChild(i - 1)
971+
or
972+
result = getUnknownExprChild(this, i)
970973
}
971974
}
972975

@@ -1001,6 +1004,13 @@ module ControlFlow {
10011004
i = 0 and result = ae.getExpr()
10021005
}
10031006

1007+
private ControlFlowElement getUnknownExprChild(@unknown_expr e, int i) {
1008+
exists(int c |
1009+
result = e.(Expr).getChild(c) |
1010+
c = rank[i+1](int j | exists(e.(Expr).getChild(j)))
1011+
)
1012+
}
1013+
10041014
private ControlFlowElement getCastExprChild(CastExpr ce, int i) {
10051015
// The type access at index 1 is not evaluated at run-time
10061016
i = 0 and result = ce.getExpr()
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// semmle-extractor-options: --standalone
2+
3+
using System;
4+
5+
class Cfg
6+
{
7+
void F()
8+
{
9+
var v = new InvalidType();
10+
Debug.Assert(v.a.b, "This is true");
11+
12+
new CounterCreationData() { CounterHelp = string.Empty, CounterType = v.Type };
13+
}
14+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
| ControlFlow.cs:7:10:7:10 | enter F | ControlFlow.cs:8:5:13:5 | {...} |
2+
| ControlFlow.cs:8:5:13:5 | {...} | ControlFlow.cs:9:9:9:34 | ... ...; |
3+
| ControlFlow.cs:9:9:9:34 | ... ...; | ControlFlow.cs:9:13:9:13 | access to local variable v |
4+
| ControlFlow.cs:10:9:10:13 | Expression | ControlFlow.cs:10:22:10:22 | access to local variable v |
5+
| ControlFlow.cs:10:9:10:43 | Call to unknown method | ControlFlow.cs:12:9:12:87 | ...; |
6+
| ControlFlow.cs:10:9:10:44 | ...; | ControlFlow.cs:10:9:10:13 | Expression |
7+
| ControlFlow.cs:10:22:10:22 | access to local variable v | ControlFlow.cs:10:22:10:24 | Expression |
8+
| ControlFlow.cs:10:22:10:24 | Expression | ControlFlow.cs:10:22:10:26 | Expression |
9+
| ControlFlow.cs:10:22:10:26 | Expression | ControlFlow.cs:10:29:10:42 | "This is true" |
10+
| ControlFlow.cs:10:29:10:42 | "This is true" | ControlFlow.cs:10:9:10:43 | Call to unknown method |
11+
| ControlFlow.cs:12:35:12:86 | { ..., ... } | ControlFlow.cs:7:10:7:10 | exit F |
12+
| ControlFlow.cs:12:37:12:47 | Expression | ControlFlow.cs:12:51:12:62 | access to field Empty |
13+
| ControlFlow.cs:12:37:12:62 | ... = ... | ControlFlow.cs:12:65:12:75 | Expression |
14+
| ControlFlow.cs:12:51:12:62 | access to field Empty | ControlFlow.cs:12:37:12:62 | ... = ... |
15+
| ControlFlow.cs:12:65:12:75 | Expression | ControlFlow.cs:12:79:12:79 | access to local variable v |
16+
| ControlFlow.cs:12:65:12:84 | ... = ... | ControlFlow.cs:12:35:12:86 | { ..., ... } |
17+
| ControlFlow.cs:12:79:12:79 | access to local variable v | ControlFlow.cs:12:79:12:84 | Expression |
18+
| ControlFlow.cs:12:79:12:84 | Expression | ControlFlow.cs:12:65:12:84 | ... = ... |
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import csharp
2+
import semmle.code.csharp.controlflow.ControlFlowGraph
3+
4+
/**
5+
* A method call where the target is unknown.
6+
* The purpose of this is to ensure that all MethodCall expressions
7+
* have a valid `toString()`.
8+
*/
9+
class UnknownCall extends MethodCall {
10+
UnknownCall() { not exists(this.getTarget()) }
11+
12+
override string toString() { result = "Call to unknown method" }
13+
}
14+
15+
query predicate edges(ControlFlow::Node n1, ControlFlow::Node n2) {
16+
n2 = n1.getASuccessor()
17+
}

0 commit comments

Comments
 (0)