@@ -31,6 +31,25 @@ class Guard extends Expr {
3131 predicate controlsNode ( ControlFlow:: Nodes:: ElementNode cfn , AccessOrCallExpr sub , AbstractValue v ) {
3232 isGuardedByNode ( cfn , this , sub , v )
3333 }
34+
35+ /**
36+ * Holds if basic block `bb` is guarded by this expression having value `v`.
37+ */
38+ predicate controlsBasicBlock ( BasicBlock bb , AbstractValue v ) {
39+ Internal:: guardControls ( this , bb , v )
40+ }
41+
42+ /**
43+ * Holds if this guard is an equality test between `e1` and `e2`. If the test is
44+ * negated, that is `!=`, then `polarity` is false, otherwise `polarity` is
45+ * true.
46+ */
47+ predicate isEquality ( Expr e1 , Expr e2 , boolean polarity ) {
48+ exists ( BooleanValue v |
49+ this = Internal:: getAnEqualityCheck ( e1 , v , e2 ) and
50+ polarity = v .getValue ( )
51+ )
52+ }
3453}
3554
3655/** An abstract value. */
@@ -943,31 +962,28 @@ module Internal {
943962 e = any ( BinaryArithmeticOperation bao | result = bao .getAnOperand ( ) )
944963 }
945964
946- /** Holds if basic block `bb` only is reached when guard `g` has abstract value `v`. */
947- private predicate guardControls ( Guard g , BasicBlock bb , AbstractValue v ) {
948- exists ( ControlFlowElement cfe , ConditionalSuccessor s , AbstractValue v0 , Guard g0 |
949- cfe .controlsBlock ( bb , s )
950- |
951- v0 .branch ( cfe , s , g0 ) and
952- impliesSteps ( g0 , v0 , g , v )
965+ pragma [ noinline]
966+ private predicate assertionControlsNodeInSameBasicBlock0 (
967+ Guard g , AbstractValue v , BasicBlock bb , int i
968+ ) {
969+ exists ( Assertion a , Guard g0 , AbstractValue v0 |
970+ asserts ( a , g0 , v0 ) and
971+ impliesSteps ( g0 , v0 , g , v ) and
972+ bb .getNode ( i ) = a .getAControlFlowNode ( )
953973 )
954974 }
955975
956976 /**
957977 * Holds if control flow node `cfn` only is reached when guard `g` evaluates to `v`,
958978 * because of an assertion.
959979 */
960- private predicate guardAssertionControlsNode ( Guard g , ControlFlow:: Node cfn , AbstractValue v ) {
961- exists ( Assertion a , Guard g0 , AbstractValue v0 |
962- asserts ( a , g0 , v0 ) and
963- impliesSteps ( g0 , v0 , g , v )
964- |
965- a .strictlyDominates ( cfn .getBasicBlock ( ) )
966- or
967- exists ( BasicBlock bb , int i , int j | bb .getNode ( i ) = a .getAControlFlowNode ( ) |
968- bb .getNode ( j ) = cfn and
969- j > i
970- )
980+ private predicate assertionControlsNodeInSameBasicBlock (
981+ Guard g , ControlFlow:: Node cfn , AbstractValue v
982+ ) {
983+ exists ( BasicBlock bb , int i , int j |
984+ assertionControlsNodeInSameBasicBlock0 ( g , v , bb , i ) and
985+ bb .getNode ( j ) = cfn and
986+ j > i
971987 )
972988 }
973989
@@ -977,7 +993,7 @@ module Internal {
977993 */
978994 private predicate guardAssertionControlsElement ( Guard g , ControlFlowElement cfe , AbstractValue v ) {
979995 forex ( ControlFlow:: Node cfn | cfn = cfe .getAControlFlowNode ( ) |
980- guardAssertionControlsNode ( g , cfn , v )
996+ assertionControlsNodeInSameBasicBlock ( g , cfn , v )
981997 )
982998 }
983999
@@ -1291,24 +1307,6 @@ module Internal {
12911307 )
12921308 }
12931309
1294- /**
1295- * Gets an expression that tests whether expression `e1` is equal to
1296- * expression `e2`.
1297- *
1298- * If the returned expression has abstract value `v`, then expression `e1` is
1299- * guaranteed to be equal to `e2`, and if the returned expression has abstract
1300- * value `v.getDualValue()`, then this expression is guaranteed to be
1301- * non-equal to `e`.
1302- *
1303- * For example, if the expression `x != ""` evaluates to `false` then the
1304- * expression `x` is guaranteed to be equal to `""`.
1305- */
1306- Expr getAnEqualityCheck ( Expr e1 , AbstractValue v , Expr e2 ) {
1307- result = getABooleanEqualityCheck ( e1 , v , e2 )
1308- or
1309- result = getAMatchingEqualityCheck ( e1 , v , e2 )
1310- }
1311-
13121310 private Expr getAnEqualityCheckVal ( Expr e , AbstractValue v , AbstractValue vExpr ) {
13131311 result = getAnEqualityCheck ( e , v , vExpr .getAnExpr ( ) )
13141312 }
@@ -1464,6 +1462,29 @@ module Internal {
14641462 not e = any ( LocalVariableDeclStmt s ) .getAVariableDeclExpr ( )
14651463 }
14661464
1465+ /**
1466+ * Gets an expression that tests whether expression `e1` is equal to
1467+ * expression `e2`.
1468+ *
1469+ * If the returned expression has abstract value `v`, then expression `e1` is
1470+ * guaranteed to be equal to `e2`, and if the returned expression has abstract
1471+ * value `v.getDualValue()`, then this expression is guaranteed to be
1472+ * non-equal to `e`.
1473+ *
1474+ * For example, if the expression `x != ""` evaluates to `false` then the
1475+ * expression `x` is guaranteed to be equal to `""`.
1476+ */
1477+ cached
1478+ Expr getAnEqualityCheck ( Expr e1 , AbstractValue v , Expr e2 ) {
1479+ result = getABooleanEqualityCheck ( e1 , v , e2 )
1480+ or
1481+ result = getABooleanEqualityCheck ( e2 , v , e1 )
1482+ or
1483+ result = getAMatchingEqualityCheck ( e1 , v , e2 )
1484+ or
1485+ result = getAMatchingEqualityCheck ( e2 , v , e1 )
1486+ }
1487+
14671488 cached
14681489 predicate isCustomNullCheck ( Call call , Expr arg , BooleanValue v , boolean isNull ) {
14691490 exists ( Callable callable , Parameter p |
@@ -1749,7 +1770,7 @@ module Internal {
17491770 exists ( Guard g | e = getAChildExprStar ( g ) |
17501771 guardControls ( g , bb , _)
17511772 or
1752- guardAssertionControlsNode ( g , bb .getANode ( ) , _)
1773+ assertionControlsNodeInSameBasicBlock ( g , bb .getANode ( ) , _)
17531774 )
17541775 }
17551776 }
@@ -1758,6 +1779,21 @@ module Internal {
17581779 private module Cached {
17591780 private import semmle.code.csharp.Caching
17601781
1782+ /** Holds if basic block `bb` only is reached when guard `g` has abstract value `v`. */
1783+ cached
1784+ predicate guardControls ( Guard g , BasicBlock bb , AbstractValue v ) {
1785+ exists ( AbstractValue v0 , Guard g0 | impliesSteps ( g0 , v0 , g , v ) |
1786+ exists ( ControlFlowElement cfe , ConditionalSuccessor s |
1787+ v0 .branch ( cfe , s , g0 ) and cfe .controlsBlock ( bb , s )
1788+ )
1789+ or
1790+ exists ( Assertion a |
1791+ asserts ( a , g0 , v0 ) and
1792+ a .strictlyDominates ( bb )
1793+ )
1794+ )
1795+ }
1796+
17611797 pragma [ noinline]
17621798 private predicate isGuardedByNode0 (
17631799 ControlFlow:: Node cfn , AccessOrCallExpr guarded , Guard g , AccessOrCallExpr sub ,
@@ -1813,7 +1849,7 @@ module Internal {
18131849 ) {
18141850 isGuardedByNode0 ( guarded , _, g , sub , v )
18151851 or
1816- guardAssertionControlsNode ( g , guarded , v ) and
1852+ assertionControlsNodeInSameBasicBlock ( g , guarded , v ) and
18171853 exists ( ConditionOnExprComparisonConfig c | c .same ( sub , guarded .getElement ( ) ) )
18181854 }
18191855
0 commit comments