Skip to content

Commit e2f271b

Browse files
committed
C#: Add more guard implication steps
1 parent 078dc7b commit e2f271b

File tree

3 files changed

+65
-3
lines changed

3 files changed

+65
-3
lines changed

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

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -694,7 +694,7 @@ module Internal {
694694
predicate preControls(PreBasicBlocks::PreBasicBlock bb, AbstractValue v) {
695695
exists(AbstractValue v0, Guard g |
696696
g.preControlsDirect(bb, v0) |
697-
impliesSteps(g, v0, this, v)
697+
preImpliesSteps(g, v0, this, v)
698698
)
699699
}
700700

@@ -781,7 +781,7 @@ module Internal {
781781
def.nullGuardedReturn(ret, isNull)
782782
or
783783
exists(NullValue nv |
784-
impliesSteps(ret, retVal, def.getARead(), nv) |
784+
preImpliesSteps(ret, retVal, def.getARead(), nv) |
785785
if nv.isNull() then isNull = true else isNull = false
786786
)
787787
)
@@ -1123,6 +1123,28 @@ module Internal {
11231123
def = guarded.getAnSsaQualifier()
11241124
)
11251125
}
1126+
1127+
/**
1128+
* Holds if the assumption that `g1` has abstract value `v1` implies that
1129+
* `g2` has abstract value `v2`, using one step of reasoning. That is, the
1130+
* evaluation of `g2` to `v2` dominates the evaluation of `g1` to `v1`.
1131+
*
1132+
* This predicate relies on the control flow graph.
1133+
*/
1134+
cached
1135+
predicate impliesStep(Guard g1, AbstractValue v1, Guard g2, AbstractValue v2) {
1136+
preImpliesStep(g1, v1, g2, v2)
1137+
or
1138+
forex(ControlFlow::Node cfn |
1139+
cfn = g1.getAControlFlowNode() |
1140+
exists(Ssa::ExplicitDefinition def |
1141+
def.getADefinition().getSource() = g2 |
1142+
g1 = def.getAReadAtNode(cfn) and
1143+
v1 = g1.getAValue() and
1144+
v2 = v1
1145+
)
1146+
)
1147+
}
11261148
}
11271149
import Cached
11281150

@@ -1143,9 +1165,11 @@ module Internal {
11431165
* Holds if the assumption that `g1` has abstract value `v1` implies that
11441166
* `g2` has abstract value `v2`, using one step of reasoning. That is, the
11451167
* evaluation of `g2` to `v2` dominates the evaluation of `g1` to `v1`.
1168+
*
1169+
* This predicate does not rely on the control flow graph.
11461170
*/
11471171
cached
1148-
predicate impliesStep(Guard g1, AbstractValue v1, Guard g2, AbstractValue v2) {
1172+
predicate preImpliesStep(Guard g1, AbstractValue v1, Guard g2, AbstractValue v2) {
11491173
g1 = any(BinaryOperation bo |
11501174
(
11511175
bo instanceof BitwiseAndExpr or
@@ -1279,6 +1303,26 @@ module Internal {
12791303
* Holds if the assumption that `g1` has abstract value `v1` implies that
12801304
* `g2` has abstract value `v2`, using zero or more steps of reasoning. That is,
12811305
* the evaluation of `g2` to `v2` dominates the evaluation of `g1` to `v1`.
1306+
*
1307+
* This predicate does not rely on the control flow graph.
1308+
*/
1309+
predicate preImpliesSteps(Guard g1, AbstractValue v1, Guard g2, AbstractValue v2) {
1310+
g1 = g2 and
1311+
v1 = v2 and
1312+
v1 = g1.getAValue()
1313+
or
1314+
exists(Expr mid, AbstractValue vMid |
1315+
preImpliesSteps(g1, v1, mid, vMid) |
1316+
preImpliesStep(mid, vMid, g2, v2)
1317+
)
1318+
}
1319+
1320+
/**
1321+
* Holds if the assumption that `g1` has abstract value `v1` implies that
1322+
* `g2` has abstract value `v2`, using zero or more steps of reasoning. That is,
1323+
* the evaluation of `g2` to `v2` dominates the evaluation of `g1` to `v1`.
1324+
*
1325+
* This predicate relies on the control flow graph.
12821326
*/
12831327
predicate impliesSteps(Guard g1, AbstractValue v1, Guard g2, AbstractValue v2) {
12841328
g1 = g2 and

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,10 @@
251251
| Guards.cs:106:9:106:25 | ... = ... | non-null | Guards.cs:106:22:106:25 | null | non-null |
252252
| Guards.cs:106:9:106:25 | ... = ... | null | Guards.cs:106:9:106:18 | access to property Property | null |
253253
| Guards.cs:106:9:106:25 | ... = ... | null | Guards.cs:106:22:106:25 | null | null |
254+
| Guards.cs:107:27:107:36 | access to property Property | non-null | Guards.cs:106:22:106:25 | null | non-null |
255+
| Guards.cs:107:27:107:36 | access to property Property | null | Guards.cs:106:22:106:25 | null | null |
256+
| Guards.cs:108:27:108:36 | access to property Property | non-null | Guards.cs:106:22:106:25 | null | non-null |
257+
| Guards.cs:108:27:108:36 | access to property Property | null | Guards.cs:106:22:106:25 | null | null |
254258
| Guards.cs:113:13:114:38 | String dummy = ... | non-null | Guards.cs:113:13:113:17 | access to local variable dummy | non-null |
255259
| Guards.cs:113:13:114:38 | String dummy = ... | null | Guards.cs:113:13:113:17 | access to local variable dummy | null |
256260
| Guards.cs:115:9:115:55 | ... = ... | non-null | Guards.cs:115:9:115:13 | access to local variable dummy | non-null |
@@ -261,6 +265,10 @@
261265
| Guards.cs:117:9:117:25 | ... = ... | non-null | Guards.cs:117:22:117:25 | null | non-null |
262266
| Guards.cs:117:9:117:25 | ... = ... | null | Guards.cs:117:9:117:18 | access to property Property | null |
263267
| Guards.cs:117:9:117:25 | ... = ... | null | Guards.cs:117:22:117:25 | null | null |
268+
| Guards.cs:118:27:118:36 | access to property Property | non-null | Guards.cs:117:22:117:25 | null | non-null |
269+
| Guards.cs:118:27:118:36 | access to property Property | null | Guards.cs:117:22:117:25 | null | null |
270+
| Guards.cs:119:27:119:36 | access to property Property | non-null | Guards.cs:117:22:117:25 | null | non-null |
271+
| Guards.cs:119:27:119:36 | access to property Property | null | Guards.cs:117:22:117:25 | null | null |
264272
| Guards.cs:124:13:124:30 | Boolean b1 = ... | false | Guards.cs:124:13:124:14 | access to local variable b1 | false |
265273
| Guards.cs:124:13:124:30 | Boolean b1 = ... | true | Guards.cs:124:13:124:14 | access to local variable b1 | true |
266274
| Guards.cs:125:13:125:31 | Nullable<Boolean> b2 = ... | non-null | Guards.cs:125:13:125:14 | access to local variable b2 | non-null |

csharp/ql/test/query-tests/Nullness/Implications.expected

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -930,6 +930,8 @@
930930
| D.cs:187:13:187:28 | ... = ... | non-null | D.cs:187:20:187:28 | call to method MkMaybe | non-null |
931931
| D.cs:187:13:187:28 | ... = ... | null | D.cs:187:13:187:16 | access to local variable obj3 | null |
932932
| D.cs:187:13:187:28 | ... = ... | null | D.cs:187:20:187:28 | call to method MkMaybe | null |
933+
| D.cs:190:9:190:12 | access to local variable obj3 | non-null | D.cs:187:20:187:28 | call to method MkMaybe | non-null |
934+
| D.cs:190:9:190:12 | access to local variable obj3 | null | D.cs:187:20:187:28 | call to method MkMaybe | null |
933935
| D.cs:195:13:195:28 | Object o = ... | non-null | D.cs:195:13:195:13 | access to local variable o | non-null |
934936
| D.cs:195:13:195:28 | Object o = ... | null | D.cs:195:13:195:13 | access to local variable o | null |
935937
| D.cs:196:13:196:13 | access to local variable o | non-null | D.cs:195:17:195:28 | object creation of type Object | non-null |
@@ -985,6 +987,8 @@
985987
| D.cs:230:13:230:28 | ... = ... | non-null | D.cs:230:17:230:28 | object creation of type Object | non-null |
986988
| D.cs:230:13:230:28 | ... = ... | null | D.cs:230:13:230:13 | access to local variable o | null |
987989
| D.cs:230:13:230:28 | ... = ... | null | D.cs:230:17:230:28 | object creation of type Object | null |
990+
| D.cs:232:13:232:13 | access to local variable o | non-null | D.cs:230:17:230:28 | object creation of type Object | non-null |
991+
| D.cs:232:13:232:13 | access to local variable o | null | D.cs:230:17:230:28 | object creation of type Object | null |
988992
| D.cs:234:9:234:16 | ... = ... | non-null | D.cs:234:9:234:9 | access to local variable o | non-null |
989993
| D.cs:234:9:234:16 | ... = ... | non-null | D.cs:234:13:234:16 | null | non-null |
990994
| D.cs:234:9:234:16 | ... = ... | null | D.cs:234:9:234:9 | access to local variable o | null |
@@ -993,6 +997,8 @@
993997
| D.cs:236:13:236:18 | ... = ... | non-null | D.cs:236:17:236:18 | "" | non-null |
994998
| D.cs:236:13:236:18 | ... = ... | null | D.cs:236:13:236:13 | access to local variable o | null |
995999
| D.cs:236:13:236:18 | ... = ... | null | D.cs:236:17:236:18 | "" | null |
1000+
| D.cs:238:13:238:13 | access to local variable o | non-null | D.cs:236:17:236:18 | "" | non-null |
1001+
| D.cs:238:13:238:13 | access to local variable o | null | D.cs:236:17:236:18 | "" | null |
9961002
| D.cs:240:9:240:16 | ... = ... | non-null | D.cs:240:9:240:9 | access to local variable o | non-null |
9971003
| D.cs:240:9:240:16 | ... = ... | non-null | D.cs:240:13:240:16 | null | non-null |
9981004
| D.cs:240:9:240:16 | ... = ... | null | D.cs:240:9:240:9 | access to local variable o | null |
@@ -1410,12 +1416,16 @@
14101416
| E.cs:217:13:217:20 | ... = ... | non-null | E.cs:217:17:217:20 | null | non-null |
14111417
| E.cs:217:13:217:20 | ... = ... | null | E.cs:217:13:217:13 | access to local variable x | null |
14121418
| E.cs:217:13:217:20 | ... = ... | null | E.cs:217:17:217:20 | null | null |
1419+
| E.cs:220:13:220:13 | access to local variable x | non-null | E.cs:217:17:217:20 | null | non-null |
1420+
| E.cs:220:13:220:13 | access to local variable x | null | E.cs:217:17:217:20 | null | null |
14131421
| E.cs:225:13:225:18 | String x = ... | non-null | E.cs:225:13:225:13 | access to local variable x | non-null |
14141422
| E.cs:225:13:225:18 | String x = ... | null | E.cs:225:13:225:13 | access to local variable x | null |
14151423
| E.cs:227:13:227:20 | ... = ... | non-null | E.cs:227:13:227:13 | access to local variable x | non-null |
14161424
| E.cs:227:13:227:20 | ... = ... | non-null | E.cs:227:17:227:20 | null | non-null |
14171425
| E.cs:227:13:227:20 | ... = ... | null | E.cs:227:13:227:13 | access to local variable x | null |
14181426
| E.cs:227:13:227:20 | ... = ... | null | E.cs:227:17:227:20 | null | null |
1427+
| E.cs:229:13:229:13 | access to local variable x | non-null | E.cs:227:17:227:20 | null | non-null |
1428+
| E.cs:229:13:229:13 | access to local variable x | null | E.cs:227:17:227:20 | null | null |
14191429
| E.cs:245:13:245:22 | access to property HasValue | false | E.cs:245:13:245:13 | access to parameter i | null |
14201430
| E.cs:245:13:245:22 | access to property HasValue | true | E.cs:245:13:245:13 | access to parameter i | non-null |
14211431
| E.cs:252:13:252:21 | ... != ... | false | E.cs:252:13:252:13 | access to parameter i | null |

0 commit comments

Comments
 (0)