Skip to content

Commit e79a906

Browse files
committed
C#: Fix CFG for fall-through switch statements
1 parent a991ef0 commit e79a906

File tree

8 files changed

+19
-32
lines changed

8 files changed

+19
-32
lines changed

csharp/ql/lib/semmle/code/csharp/Stmt.qll

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -278,9 +278,14 @@ class CaseStmt extends Case, @case_stmt {
278278
override PatternExpr getPattern() { result = this.getChild(0) }
279279

280280
override Stmt getBody() {
281-
exists(int i |
281+
exists(int i, Stmt next |
282282
this = this.getParent().getChild(i) and
283-
result = this.getParent().getChild(i + 1)
283+
next = this.getParent().getChild(i + 1)
284+
|
285+
result = next and
286+
not result instanceof CaseStmt
287+
or
288+
result = next.(CaseStmt).getBody()
284289
)
285290
}
286291

csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1153,7 +1153,13 @@ module Statements {
11531153
)
11541154
or
11551155
// Flow from last element of `case` statement `i` to first element of statement `i+1`
1156-
exists(int i | last(super.getStmt(i).(CaseStmt).getBody(), pred, c) |
1156+
exists(int i, Stmt body |
1157+
body = super.getStmt(i).(CaseStmt).getBody() and
1158+
// in case of fall-through cases, make sure to not jump from their shared body back
1159+
// to one of the fall-through cases
1160+
not body = super.getStmt(i + 1).(CaseStmt).getBody() and
1161+
last(body, pred, c)
1162+
|
11571163
c instanceof NormalCompletion and
11581164
first(super.getStmt(i + 1), succ)
11591165
)

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,8 +1081,7 @@
10811081
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:167:18:167:18 | 1 | 6 |
10821082
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:163:10:163:12 | exit M16 | 2 |
10831083
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:168:18:168:18 | 2 | 2 |
1084-
| Switch.cs:169:17:169:51 | ...; | Switch.cs:169:17:169:50 | call to method WriteLine | 3 |
1085-
| Switch.cs:170:17:170:22 | break; | Switch.cs:170:17:170:22 | break; | 1 |
1084+
| Switch.cs:169:17:169:51 | ...; | Switch.cs:170:17:170:22 | break; | 4 |
10861085
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:171:18:171:18 | 3 | 2 |
10871086
| Switch.cs:172:17:172:46 | ...; | Switch.cs:173:17:173:22 | break; | 4 |
10881087
| Switch.cs:174:13:174:20 | default: | Switch.cs:176:17:176:22 | break; | 5 |

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

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,21 +2140,10 @@ conditionBlock
21402140
| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:158:13:158:49 | ...; | true |
21412141
| Switch.cs:156:17:156:54 | ... switch { ... } | Switch.cs:160:13:160:49 | ...; | false |
21422142
| Switch.cs:156:41:156:45 | false | Switch.cs:156:50:156:52 | "b" | true |
2143-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:163:10:163:12 | exit M16 (normal) | false |
2144-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:163:10:163:12 | exit M16 (normal) | true |
21452143
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:168:13:168:19 | case ...: | false |
2146-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:168:13:168:19 | case ...: | true |
2147-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:169:17:169:51 | ...; | false |
2148-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:169:17:169:51 | ...; | true |
2149-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:170:17:170:22 | break; | false |
2150-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:170:17:170:22 | break; | true |
21512144
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:171:13:171:19 | case ...: | false |
2152-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:171:13:171:19 | case ...: | true |
21532145
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:172:17:172:46 | ...; | false |
2154-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:172:17:172:46 | ...; | true |
21552146
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:174:13:174:20 | default: | false |
2156-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:174:13:174:20 | default: | true |
2157-
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:169:17:169:51 | ...; | true |
21582147
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:171:13:171:19 | case ...: | false |
21592148
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:172:17:172:46 | ...; | false |
21602149
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:174:13:174:20 | default: | false |

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

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3685,10 +3685,10 @@ dominance
36853685
| Switch.cs:165:17:165:17 | access to parameter i | Switch.cs:167:13:167:19 | case ...: |
36863686
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:167:18:167:18 | 1 |
36873687
| Switch.cs:167:18:167:18 | 1 | Switch.cs:168:13:168:19 | case ...: |
3688+
| Switch.cs:167:18:167:18 | 1 | Switch.cs:169:17:169:51 | ...; |
36883689
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:168:18:168:18 | 2 |
3689-
| Switch.cs:168:18:168:18 | 2 | Switch.cs:169:17:169:51 | ...; |
3690-
| Switch.cs:168:18:168:18 | 2 | Switch.cs:170:17:170:22 | break; |
36913690
| Switch.cs:168:18:168:18 | 2 | Switch.cs:171:13:171:19 | case ...: |
3691+
| Switch.cs:169:17:169:50 | call to method WriteLine | Switch.cs:170:17:170:22 | break; |
36923692
| Switch.cs:169:17:169:51 | ...; | Switch.cs:169:42:169:49 | "1 or 2" |
36933693
| Switch.cs:169:42:169:49 | "1 or 2" | Switch.cs:169:17:169:50 | call to method WriteLine |
36943694
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:171:18:171:18 | 3 |
@@ -7886,7 +7886,6 @@ postDominance
78867886
| Switch.cs:165:17:165:17 | access to parameter i | Switch.cs:165:9:177:9 | switch (...) {...} |
78877887
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:165:17:165:17 | access to parameter i |
78887888
| Switch.cs:167:18:167:18 | 1 | Switch.cs:167:13:167:19 | case ...: |
7889-
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:167:18:167:18 | 1 |
78907889
| Switch.cs:168:18:168:18 | 2 | Switch.cs:168:13:168:19 | case ...: |
78917890
| Switch.cs:169:17:169:50 | call to method WriteLine | Switch.cs:169:42:169:49 | "1 or 2" |
78927891
| Switch.cs:169:42:169:49 | "1 or 2" | Switch.cs:169:17:169:51 | ...; |
@@ -12516,20 +12515,15 @@ blockDominance
1251612515
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:163:10:163:12 | exit M16 (normal) |
1251712516
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:168:13:168:19 | case ...: |
1251812517
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:169:17:169:51 | ...; |
12519-
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:170:17:170:22 | break; |
1252012518
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:171:13:171:19 | case ...: |
1252112519
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:172:17:172:46 | ...; |
1252212520
| Switch.cs:163:10:163:12 | enter M16 | Switch.cs:174:13:174:20 | default: |
1252312521
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:163:10:163:12 | exit M16 (normal) |
12524-
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:163:10:163:12 | exit M16 (normal) |
1252512522
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:168:13:168:19 | case ...: |
12526-
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:169:17:169:51 | ...; |
12527-
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:170:17:170:22 | break; |
1252812523
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:171:13:171:19 | case ...: |
1252912524
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:172:17:172:46 | ...; |
1253012525
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:174:13:174:20 | default: |
1253112526
| Switch.cs:169:17:169:51 | ...; | Switch.cs:169:17:169:51 | ...; |
12532-
| Switch.cs:170:17:170:22 | break; | Switch.cs:170:17:170:22 | break; |
1253312527
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:171:13:171:19 | case ...: |
1253412528
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:172:17:172:46 | ...; |
1253512529
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:174:13:174:20 | default: |
@@ -15867,15 +15861,11 @@ postBlockDominance
1586715861
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:163:10:163:12 | exit M16 (normal) |
1586815862
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:168:13:168:19 | case ...: |
1586915863
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:169:17:169:51 | ...; |
15870-
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:170:17:170:22 | break; |
1587115864
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:171:13:171:19 | case ...: |
1587215865
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:172:17:172:46 | ...; |
1587315866
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:174:13:174:20 | default: |
15874-
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:163:10:163:12 | enter M16 |
1587515867
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:168:13:168:19 | case ...: |
1587615868
| Switch.cs:169:17:169:51 | ...; | Switch.cs:169:17:169:51 | ...; |
15877-
| Switch.cs:170:17:170:22 | break; | Switch.cs:169:17:169:51 | ...; |
15878-
| Switch.cs:170:17:170:22 | break; | Switch.cs:170:17:170:22 | break; |
1587915869
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:171:13:171:19 | case ...: |
1588015870
| Switch.cs:172:17:172:46 | ...; | Switch.cs:172:17:172:46 | ...; |
1588115871
| Switch.cs:174:13:174:20 | default: | Switch.cs:174:13:174:20 | default: |

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5942,7 +5942,6 @@ blockEnclosing
59425942
| Switch.cs:163:10:163:12 | exit M16 (normal) | Switch.cs:163:10:163:12 | M16 |
59435943
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:163:10:163:12 | M16 |
59445944
| Switch.cs:169:17:169:51 | ...; | Switch.cs:163:10:163:12 | M16 |
5945-
| Switch.cs:170:17:170:22 | break; | Switch.cs:163:10:163:12 | M16 |
59465945
| Switch.cs:171:13:171:19 | case ...: | Switch.cs:163:10:163:12 | M16 |
59475946
| Switch.cs:172:17:172:46 | ...; | Switch.cs:163:10:163:12 | M16 |
59485947
| Switch.cs:174:13:174:20 | default: | Switch.cs:163:10:163:12 | M16 |

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3589,7 +3589,6 @@
35893589
| Switch.cs:165:9:177:9 | switch (...) {...} | Switch.cs:176:17:176:22 | break; | normal [break] (0) |
35903590
| Switch.cs:165:17:165:17 | access to parameter i | Switch.cs:165:17:165:17 | access to parameter i | normal |
35913591
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:167:18:167:18 | 1 | no-match |
3592-
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:168:18:168:18 | 2 | no-match |
35933592
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:169:17:169:50 | call to method WriteLine | normal |
35943593
| Switch.cs:167:18:167:18 | 1 | Switch.cs:167:18:167:18 | 1 | match |
35953594
| Switch.cs:167:18:167:18 | 1 | Switch.cs:167:18:167:18 | 1 | no-match |

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4151,10 +4151,10 @@
41514151
| Switch.cs:165:9:177:9 | switch (...) {...} | Switch.cs:165:17:165:17 | access to parameter i | |
41524152
| Switch.cs:165:17:165:17 | access to parameter i | Switch.cs:167:13:167:19 | case ...: | |
41534153
| Switch.cs:167:13:167:19 | case ...: | Switch.cs:167:18:167:18 | 1 | |
4154-
| Switch.cs:167:18:167:18 | 1 | Switch.cs:168:13:168:19 | case ...: | match, no-match |
4154+
| Switch.cs:167:18:167:18 | 1 | Switch.cs:168:13:168:19 | case ...: | no-match |
4155+
| Switch.cs:167:18:167:18 | 1 | Switch.cs:169:17:169:51 | ...; | match |
41554156
| Switch.cs:168:13:168:19 | case ...: | Switch.cs:168:18:168:18 | 2 | |
41564157
| Switch.cs:168:18:168:18 | 2 | Switch.cs:169:17:169:51 | ...; | match |
4157-
| Switch.cs:168:18:168:18 | 2 | Switch.cs:170:17:170:22 | break; | no-match |
41584158
| Switch.cs:168:18:168:18 | 2 | Switch.cs:171:13:171:19 | case ...: | no-match |
41594159
| Switch.cs:169:17:169:50 | call to method WriteLine | Switch.cs:170:17:170:22 | break; | |
41604160
| Switch.cs:169:17:169:51 | ...; | Switch.cs:169:42:169:49 | "1 or 2" | |

0 commit comments

Comments
 (0)