Skip to content

Commit e86db3c

Browse files
authored
Merge pull request #4725 from hvitved/csharp/cfg/constant-condition-block
C#: Always create basic blocks for nodes with a conditional predecessor
2 parents 931322e + d4ee8cd commit e86db3c

File tree

12 files changed

+4191
-286
lines changed

12 files changed

+4191
-286
lines changed

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,19 @@ private module Internal {
298298
cfn.isJoin()
299299
or
300300
cfn.getAPredecessor().isBranch()
301+
or
302+
/*
303+
* In cases such as
304+
* ```csharp
305+
* if (b)
306+
* M()
307+
* ```
308+
* where the `false` edge out of `b` is not present (because we can prove it
309+
* impossible), we still split up the basic block in two, in order to generate
310+
* a `ConditionBlock` which can be used by the guards library.
311+
*/
312+
313+
exists(cfn.getAPredecessorByType(any(ControlFlow::SuccessorTypes::ConditionalSuccessor s)))
301314
}
302315

303316
/**

csharp/ql/src/semmle/code/csharp/controlflow/internal/PreBasicBlocks.qll

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ private predicate startsBB(ControlFlowElement cfe) {
2424
or
2525
strictcount(ControlFlowElement pred, Completion c | succ(pred, cfe, c)) > 1
2626
or
27+
succ(_, cfe, any(ConditionalCompletion c))
28+
or
2729
exists(ControlFlowElement pred, int i |
2830
succ(pred, cfe, _) and
2931
i = count(ControlFlowElement succ, Completion c | succ(pred, succ, c))
@@ -95,14 +97,11 @@ private Completion getConditionalCompletion(ConditionalCompletion cc) {
9597

9698
class ConditionBlock extends PreBasicBlock {
9799
ConditionBlock() {
98-
strictcount(Completion c |
99-
c = getConditionalCompletion(_) and
100-
(
101-
succ(this.getLastElement(), _, c)
102-
or
103-
succExit(this.getLastElement(), _, c)
104-
)
105-
) > 1
100+
exists(Completion c | c = getConditionalCompletion(_) |
101+
succ(this.getLastElement(), _, c)
102+
or
103+
succExit(this.getLastElement(), _, c)
104+
)
106105
}
107106

108107
private predicate immediatelyControls(PreBasicBlock succ, ConditionalCompletion cc) {

csharp/ql/src/semmle/code/csharp/security/dataflow/TaintedPath.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ module TaintedPath {
110110
or
111111
// Checking against `null` has no bearing on path traversal.
112112
this.controlsNode(_, _, any(AbstractValues::NullValue nv))
113+
or
114+
this.(LogicalOperation).getAnOperand() instanceof WeakGuard
113115
}
114116
}
115117

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

Lines changed: 272 additions & 114 deletions
Large diffs are not rendered by default.

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

Lines changed: 1211 additions & 90 deletions
Large diffs are not rendered by default.

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

Lines changed: 2350 additions & 47 deletions
Large diffs are not rendered by default.

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

Lines changed: 158 additions & 0 deletions
Large diffs are not rendered by default.

csharp/ql/test/library-tests/controlflow/guards/BooleanGuardedExpr.expected

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,20 +5,28 @@
55
| Assert.cs:53:27:53:27 | access to local variable s | Assert.cs:52:24:52:32 | ... == ... | Assert.cs:52:24:52:24 | access to local variable s | false |
66
| Assert.cs:59:36:59:36 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | Assert.cs:58:20:58:20 | access to parameter b | false |
77
| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:31 | ... != ... | Assert.cs:59:23:59:23 | access to local variable s | true |
8+
| Assert.cs:60:27:60:27 | access to local variable s | Assert.cs:59:23:59:36 | ... && ... | Assert.cs:59:23:59:23 | access to local variable s | true |
89
| Assert.cs:66:37:66:37 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | Assert.cs:65:20:65:20 | access to parameter b | false |
910
| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:32 | ... == ... | Assert.cs:66:24:66:24 | access to local variable s | false |
11+
| Assert.cs:67:27:67:27 | access to local variable s | Assert.cs:66:24:66:37 | ... \|\| ... | Assert.cs:66:24:66:24 | access to local variable s | false |
1012
| Assert.cs:73:36:73:36 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | Assert.cs:72:20:72:20 | access to parameter b | true |
1113
| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:31 | ... == ... | Assert.cs:73:23:73:23 | access to local variable s | true |
14+
| Assert.cs:74:27:74:27 | access to local variable s | Assert.cs:73:23:73:36 | ... && ... | Assert.cs:73:23:73:23 | access to local variable s | true |
1215
| Assert.cs:80:37:80:37 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | Assert.cs:79:20:79:20 | access to parameter b | true |
1316
| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:32 | ... != ... | Assert.cs:80:24:80:24 | access to local variable s | false |
17+
| Assert.cs:81:27:81:27 | access to local variable s | Assert.cs:80:24:80:37 | ... \|\| ... | Assert.cs:80:24:80:24 | access to local variable s | false |
1418
| Assert.cs:94:16:94:17 | access to parameter b1 | Assert.cs:93:25:93:26 | access to parameter b1 | Assert.cs:93:25:93:26 | access to parameter b1 | true |
1519
| Assert.cs:94:23:94:24 | access to parameter b2 | Assert.cs:93:29:93:30 | access to parameter b2 | Assert.cs:93:29:93:30 | access to parameter b2 | false |
1620
| Collections.cs:52:17:52:20 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
1721
| Collections.cs:53:9:53:12 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
1822
| Collections.cs:54:13:54:16 | access to parameter args | Collections.cs:50:13:50:27 | ... == ... | Collections.cs:50:13:50:16 | access to parameter args | false |
1923
| Collections.cs:67:13:67:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
2024
| Collections.cs:68:13:68:13 | access to local variable x | Collections.cs:65:13:65:24 | ... == ... | Collections.cs:65:13:65:13 | access to local variable x | true |
25+
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:13:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | false |
26+
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:14:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | true |
2127
| Guards.cs:12:13:12:13 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
28+
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:13:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | false |
29+
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:14:10:25 | !... | Guards.cs:10:16:10:16 | access to parameter s | true |
2230
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:10:16:10:24 | ... == ... | Guards.cs:10:16:10:16 | access to parameter s | false |
2331
| Guards.cs:14:31:14:31 | access to parameter s | Guards.cs:12:13:12:24 | ... > ... | Guards.cs:12:13:12:13 | access to parameter s | true |
2432
| Guards.cs:26:31:26:31 | access to parameter s | Guards.cs:24:13:24:21 | ... != ... | Guards.cs:24:13:24:13 | access to parameter s | true |
@@ -29,10 +37,24 @@
2937
| Guards.cs:33:35:33:35 | access to parameter y | Guards.cs:32:40:32:51 | !... | Guards.cs:32:42:32:42 | access to parameter y | true |
3038
| Guards.cs:33:35:33:35 | access to parameter y | Guards.cs:32:42:32:50 | ... == ... | Guards.cs:32:42:32:42 | access to parameter y | false |
3139
| Guards.cs:36:32:36:32 | access to parameter x | Guards.cs:35:13:35:21 | ... == ... | Guards.cs:35:13:35:13 | access to parameter x | false |
40+
| Guards.cs:36:32:36:32 | access to parameter x | Guards.cs:35:13:35:34 | ... \|\| ... | Guards.cs:35:13:35:13 | access to parameter x | false |
41+
| Guards.cs:36:36:36:36 | access to parameter y | Guards.cs:35:13:35:34 | ... \|\| ... | Guards.cs:35:26:35:26 | access to parameter y | false |
3242
| Guards.cs:36:36:36:36 | access to parameter y | Guards.cs:35:26:35:34 | ... == ... | Guards.cs:35:26:35:26 | access to parameter y | false |
43+
| Guards.cs:39:31:39:31 | access to parameter x | Guards.cs:38:13:38:37 | !... | Guards.cs:38:15:38:15 | access to parameter x | true |
3344
| Guards.cs:39:31:39:31 | access to parameter x | Guards.cs:38:15:38:23 | ... == ... | Guards.cs:38:15:38:15 | access to parameter x | false |
45+
| Guards.cs:39:31:39:31 | access to parameter x | Guards.cs:38:15:38:36 | ... \|\| ... | Guards.cs:38:15:38:15 | access to parameter x | false |
46+
| Guards.cs:39:35:39:35 | access to parameter y | Guards.cs:38:13:38:37 | !... | Guards.cs:38:28:38:28 | access to parameter y | true |
47+
| Guards.cs:39:35:39:35 | access to parameter y | Guards.cs:38:15:38:36 | ... \|\| ... | Guards.cs:38:28:38:28 | access to parameter y | false |
3448
| Guards.cs:39:35:39:35 | access to parameter y | Guards.cs:38:28:38:36 | ... == ... | Guards.cs:38:28:38:28 | access to parameter y | false |
49+
| Guards.cs:42:32:42:32 | access to parameter x | Guards.cs:41:13:41:39 | !... | Guards.cs:41:17:41:17 | access to parameter x | false |
50+
| Guards.cs:42:32:42:32 | access to parameter x | Guards.cs:41:14:41:39 | !... | Guards.cs:41:17:41:17 | access to parameter x | true |
51+
| Guards.cs:42:32:42:32 | access to parameter x | Guards.cs:41:15:41:39 | !... | Guards.cs:41:17:41:17 | access to parameter x | false |
3552
| Guards.cs:42:32:42:32 | access to parameter x | Guards.cs:41:17:41:25 | ... != ... | Guards.cs:41:17:41:17 | access to parameter x | true |
53+
| Guards.cs:42:32:42:32 | access to parameter x | Guards.cs:41:17:41:38 | ... && ... | Guards.cs:41:17:41:17 | access to parameter x | true |
54+
| Guards.cs:42:36:42:36 | access to parameter y | Guards.cs:41:13:41:39 | !... | Guards.cs:41:30:41:30 | access to parameter y | false |
55+
| Guards.cs:42:36:42:36 | access to parameter y | Guards.cs:41:14:41:39 | !... | Guards.cs:41:30:41:30 | access to parameter y | true |
56+
| Guards.cs:42:36:42:36 | access to parameter y | Guards.cs:41:15:41:39 | !... | Guards.cs:41:30:41:30 | access to parameter y | false |
57+
| Guards.cs:42:36:42:36 | access to parameter y | Guards.cs:41:17:41:38 | ... && ... | Guards.cs:41:30:41:30 | access to parameter y | true |
3658
| Guards.cs:42:36:42:36 | access to parameter y | Guards.cs:41:30:41:38 | ... != ... | Guards.cs:41:30:41:30 | access to parameter y | true |
3759
| Guards.cs:48:31:48:40 | access to field Field | Guards.cs:47:13:47:25 | ... != ... | Guards.cs:47:13:47:17 | access to field Field | true |
3860
| Guards.cs:55:27:55:27 | access to parameter g | Guards.cs:53:13:53:27 | ... == ... | Guards.cs:53:13:53:13 | access to parameter g | false |
@@ -63,18 +85,24 @@
6385
| Guards.cs:138:20:138:20 | access to parameter s | Guards.cs:137:13:137:25 | ... is ... | Guards.cs:137:13:137:13 | access to parameter s | true |
6486
| Guards.cs:139:16:139:16 | access to parameter s | Guards.cs:137:13:137:25 | ... is ... | Guards.cs:137:13:137:13 | access to parameter s | false |
6587
| Guards.cs:146:16:146:16 | access to parameter o | Guards.cs:144:13:144:25 | ... is ... | Guards.cs:144:13:144:13 | access to parameter o | false |
88+
| Guards.cs:169:31:169:31 | access to parameter x | Guards.cs:168:13:168:41 | !... | Guards.cs:168:40:168:40 | access to parameter x | true |
6689
| Guards.cs:169:31:169:31 | access to parameter x | Guards.cs:168:14:168:41 | call to method IsNullOrWhiteSpace | Guards.cs:168:40:168:40 | access to parameter x | false |
90+
| Guards.cs:190:31:190:31 | access to parameter s | Guards.cs:189:13:189:25 | !... | Guards.cs:189:24:189:24 | access to parameter s | true |
6791
| Guards.cs:190:31:190:31 | access to parameter s | Guards.cs:189:14:189:25 | call to method NullTest1 | Guards.cs:189:24:189:24 | access to parameter s | false |
92+
| Guards.cs:192:31:192:31 | access to parameter s | Guards.cs:191:13:191:25 | !... | Guards.cs:191:24:191:24 | access to parameter s | true |
6893
| Guards.cs:192:31:192:31 | access to parameter s | Guards.cs:191:14:191:25 | call to method NullTest2 | Guards.cs:191:24:191:24 | access to parameter s | false |
94+
| Guards.cs:194:31:194:31 | access to parameter s | Guards.cs:193:13:193:25 | !... | Guards.cs:193:24:193:24 | access to parameter s | true |
6995
| Guards.cs:194:31:194:31 | access to parameter s | Guards.cs:193:14:193:25 | call to method NullTest3 | Guards.cs:193:24:193:24 | access to parameter s | false |
7096
| Guards.cs:196:31:196:31 | access to parameter s | Guards.cs:195:13:195:27 | call to method NotNullTest4 | Guards.cs:195:26:195:26 | access to parameter s | true |
97+
| Guards.cs:198:31:198:31 | access to parameter s | Guards.cs:197:13:197:29 | !... | Guards.cs:197:28:197:28 | access to parameter s | true |
7198
| Guards.cs:198:31:198:31 | access to parameter s | Guards.cs:197:14:197:29 | call to method NullTestWrong | Guards.cs:197:28:197:28 | access to parameter s | false |
7299
| Guards.cs:205:13:205:13 | access to parameter o | Guards.cs:203:13:203:21 | ... != ... | Guards.cs:203:13:203:13 | access to parameter o | true |
73100
| Guards.cs:208:17:208:17 | access to parameter o | Guards.cs:203:13:203:21 | ... != ... | Guards.cs:203:13:203:13 | access to parameter o | true |
74101
| Guards.cs:269:13:269:14 | access to parameter o1 | Guards.cs:268:13:268:41 | call to operator == | Guards.cs:268:13:268:14 | access to parameter o1 | true |
75102
| Guards.cs:271:13:271:14 | access to parameter o1 | Guards.cs:270:13:270:42 | call to operator == | Guards.cs:270:13:270:14 | access to parameter o1 | true |
76103
| Guards.cs:342:27:342:27 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | Guards.cs:341:20:341:20 | access to parameter b | false |
77104
| Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:21 | ... != ... | Guards.cs:342:13:342:13 | access to local variable s | true |
105+
| Guards.cs:343:31:343:31 | access to local variable s | Guards.cs:342:13:342:27 | ... && ... | Guards.cs:342:13:342:13 | access to local variable s | true |
78106
| Splitting.cs:13:17:13:17 | access to parameter o | Splitting.cs:12:17:12:25 | ... != ... | Splitting.cs:12:17:12:17 | access to parameter o | true |
79107
| Splitting.cs:23:24:23:24 | access to parameter o | Splitting.cs:22:17:22:25 | ... != ... | Splitting.cs:22:17:22:17 | access to parameter o | true |
80108
| Splitting.cs:25:13:25:13 | access to parameter o | Splitting.cs:22:17:22:25 | ... != ... | Splitting.cs:22:17:22:17 | access to parameter o | false |

0 commit comments

Comments
 (0)