Skip to content

Commit 9a1e148

Browse files
committed
C#: Various minor CFG bug fixes
1 parent b161ff1 commit 9a1e148

File tree

7 files changed

+127
-28
lines changed

7 files changed

+127
-28
lines changed

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

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,13 @@ module Internal {
12521252
not c instanceof GotoDefaultCompletion and
12531253
not c instanceof GotoCaseCompletion
12541254
or
1255+
// Last case exits with a non-match
1256+
exists(int last |
1257+
last = max(int i | exists(ss.getCase(i))) |
1258+
result = lastConstCaseNoMatch(ss.getCase(last), c) or
1259+
result = lastTypeCaseNoMatch(ss.getCase(last), c)
1260+
)
1261+
or
12551262
// Last statement exits with any non-break completion
12561263
exists(int last |
12571264
last = max(int i | exists(ss.getStmt(i))) |
@@ -1262,8 +1269,7 @@ module Internal {
12621269
or
12631270
cfe = any(ConstCase cc |
12641271
// Case expression exits with a non-match
1265-
result = lastConstCaseExpr(cc, c) and
1266-
c = any(MatchingCompletion mc | not mc.isMatch())
1272+
result = lastConstCaseNoMatch(cc, c)
12671273
or
12681274
// Case expression exits abnormally
12691275
result = lastConstCaseExpr(cc, c) and
@@ -1275,8 +1281,7 @@ module Internal {
12751281
or
12761282
cfe = any(TypeCase tc |
12771283
// Type test exits with a non-match
1278-
result = tc.getTypeAccess() and
1279-
c = any(MatchingCompletion mc | not mc.isMatch())
1284+
result = lastTypeCaseNoMatch(tc, c)
12801285
or
12811286
// Condition exists with a `false` completion
12821287
result = lastTypeCaseCondition(tc, c) and
@@ -1405,6 +1410,17 @@ module Internal {
14051410
)
14061411
}
14071412

1413+
private ControlFlowElement lastConstCaseNoMatch(ConstCase cc, MatchingCompletion c) {
1414+
result = lastConstCaseExpr(cc, c) and
1415+
not c.isMatch()
1416+
}
1417+
1418+
private ControlFlowElement lastTypeCaseNoMatch(TypeCase tc, MatchingCompletion c) {
1419+
result = tc.getTypeAccess() and
1420+
not c.isMatch() and
1421+
c.isValidFor(result)
1422+
}
1423+
14081424
pragma [noinline,nomagic]
14091425
private ControlFlowElement lastStandardElementGetNonLastChildElement(StandardElement se, int i, Completion c) {
14101426
result = last(se.getNonLastChildElement(i), c)
@@ -1935,7 +1951,7 @@ module Internal {
19351951
or
19361952
// Flow from last element of switch expression to first element of first statement
19371953
cfe = lastSwitchStmtCondition(ss, c) and
1938-
c instanceof SimpleCompletion and
1954+
c instanceof NormalCompletion and
19391955
result = first(ss.getStmt(0))
19401956
or
19411957
// Flow from last element of non-`case` statement `i` to first element of statement `i+1`
@@ -2123,7 +2139,7 @@ module Internal {
21232139
exists(ForeachStmt fs |
21242140
// Flow from last element of iterator expression to emptiness test
21252141
cfe = lastForeachStmtIterableExpr(fs, c) and
2126-
c instanceof SimpleCompletion and
2142+
c instanceof NormalCompletion and
21272143
result = fs
21282144
or
21292145
// Flow from emptiness test to first element of variable declaration/loop body

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

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,19 @@
217217
| Switch.cs:77:10:77:11 | enter M7 | Switch.cs:81:18:81:18 | 1 | 6 |
218218
| Switch.cs:77:10:77:11 | exit M7 | Switch.cs:77:10:77:11 | exit M7 | 1 |
219219
| Switch.cs:82:22:82:25 | true | Switch.cs:82:15:82:26 | return ...; | 2 |
220-
| Switch.cs:83:13:83:20 | case ...: | Switch.cs:84:19:84:23 | ... > ... | 6 |
221-
| Switch.cs:85:17:85:22 | break; | Switch.cs:88:9:88:21 | return ...; | 3 |
220+
| Switch.cs:83:13:83:20 | case ...: | Switch.cs:83:18:83:18 | 2 | 2 |
221+
| Switch.cs:84:15:85:22 | if (...) ... | Switch.cs:84:19:84:23 | ... > ... | 4 |
222+
| Switch.cs:85:17:85:22 | break; | Switch.cs:85:17:85:22 | break; | 1 |
222223
| Switch.cs:86:22:86:25 | true | Switch.cs:86:15:86:26 | return ...; | 2 |
224+
| Switch.cs:88:16:88:20 | false | Switch.cs:88:9:88:21 | return ...; | 2 |
223225
| Switch.cs:91:10:91:11 | enter M8 | Switch.cs:95:18:95:20 | access to type Int32 | 6 |
224226
| Switch.cs:91:10:91:11 | exit M8 | Switch.cs:91:10:91:11 | exit M8 | 1 |
225227
| Switch.cs:96:22:96:25 | true | Switch.cs:96:15:96:26 | return ...; | 2 |
226228
| Switch.cs:98:16:98:20 | false | Switch.cs:98:9:98:21 | return ...; | 2 |
227-
| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:105:18:105:18 | 0 | 7 |
229+
| Switch.cs:101:9:101:10 | enter M9 | Switch.cs:103:17:103:17 | access to parameter s | 4 |
228230
| Switch.cs:101:9:101:10 | exit M9 | Switch.cs:101:9:101:10 | exit M9 | 1 |
231+
| Switch.cs:103:19:103:25 | access to property Length | Switch.cs:103:19:103:25 | access to property Length | 1 |
232+
| Switch.cs:105:13:105:20 | case ...: | Switch.cs:105:18:105:18 | 0 | 2 |
229233
| Switch.cs:105:29:105:29 | 0 | Switch.cs:105:22:105:30 | return ...; | 2 |
230234
| Switch.cs:106:13:106:20 | case ...: | Switch.cs:106:18:106:18 | 1 | 2 |
231235
| Switch.cs:106:29:106:29 | 1 | Switch.cs:106:22:106:30 | return ...; | 2 |
@@ -265,12 +269,16 @@
265269
| cflow.cs:42:17:42:39 | ...; | cflow.cs:43:17:43:28 | goto case ...; | 5 |
266270
| cflow.cs:44:13:44:19 | case ...: | cflow.cs:44:18:44:18 | 2 | 2 |
267271
| cflow.cs:45:17:45:39 | ...; | cflow.cs:46:17:46:28 | goto case ...; | 5 |
268-
| cflow.cs:47:13:47:19 | case ...: | cflow.cs:53:18:53:19 | 42 | 10 |
272+
| cflow.cs:47:13:47:19 | case ...: | cflow.cs:47:18:47:18 | 3 | 2 |
273+
| cflow.cs:48:17:48:39 | ...; | cflow.cs:49:17:49:22 | break; | 4 |
274+
| cflow.cs:51:9:59:9 | switch (...) {...} | cflow.cs:53:18:53:19 | 42 | 4 |
269275
| cflow.cs:54:17:54:48 | ...; | cflow.cs:55:17:55:22 | break; | 4 |
270276
| cflow.cs:56:13:56:20 | default: | cflow.cs:58:17:58:22 | break; | 5 |
271-
| cflow.cs:60:9:66:9 | switch (...) {...} | cflow.cs:63:23:63:33 | ... == ... | 12 |
277+
| cflow.cs:60:9:66:9 | switch (...) {...} | cflow.cs:62:18:62:18 | 0 | 6 |
278+
| cflow.cs:63:17:64:55 | if (...) ... | cflow.cs:63:23:63:33 | ... == ... | 6 |
272279
| cflow.cs:64:27:64:54 | object creation of type NullReferenceException | cflow.cs:64:21:64:55 | throw ...; | 2 |
273-
| cflow.cs:65:17:65:22 | break; | cflow.cs:67:9:67:17 | return ...; | 3 |
280+
| cflow.cs:65:17:65:22 | break; | cflow.cs:65:17:65:22 | break; | 1 |
281+
| cflow.cs:67:16:67:16 | access to parameter a | cflow.cs:67:9:67:17 | return ...; | 2 |
274282
| cflow.cs:70:18:70:18 | enter M | cflow.cs:72:13:72:21 | ... == ... | 6 |
275283
| cflow.cs:70:18:70:18 | exit M | cflow.cs:70:18:70:18 | exit M | 1 |
276284
| cflow.cs:73:13:73:19 | return ...; | cflow.cs:73:13:73:19 | return ...; | 1 |

0 commit comments

Comments
 (0)