@@ -33,29 +33,21 @@ class Guard extends Expr {
3333 }
3434
3535 /**
36- * Holds if guard is an equality test between `e1` and `e2`. If the test is
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
3744 * negated, that is `!=`, then `polarity` is false, otherwise `polarity` is
3845 * true.
3946 */
4047 predicate isEquality ( Expr e1 , Expr e2 , boolean polarity ) {
41- exists ( Expr exp1 , Expr exp2 | equalityGuard ( exp1 , exp2 , polarity ) |
42- e1 = exp1 and e2 = exp2
43- or
44- e2 = exp1 and e1 = exp2
45- )
46- }
47-
48- private predicate equalityGuard ( Expr e1 , Expr e2 , boolean polarity ) {
49- exists ( ComparisonTest eqtest |
50- eqtest .getExpr ( ) = this and
51- eqtest .getAnArgument ( ) = e1 and
52- eqtest .getAnArgument ( ) = e2 and
53- not e1 = e2 and
54- (
55- polarity = true and eqtest .getComparisonKind ( ) .isEquality ( )
56- or
57- polarity = false and eqtest .getComparisonKind ( ) .isInequality ( )
58- )
48+ exists ( BooleanValue v |
49+ this = Internal:: getAnEqualityCheck ( e1 , v , e2 ) and
50+ polarity = v .getValue ( )
5951 )
6052 }
6153}
@@ -970,31 +962,28 @@ module Internal {
970962 e = any ( BinaryArithmeticOperation bao | result = bao .getAnOperand ( ) )
971963 }
972964
973- /** Holds if basic block `bb` only is reached when guard `g` has abstract value `v`. */
974- private predicate guardControls ( Guard g , BasicBlock bb , AbstractValue v ) {
975- exists ( ControlFlowElement cfe , ConditionalSuccessor s , AbstractValue v0 , Guard g0 |
976- cfe .controlsBlock ( bb , s )
977- |
978- v0 .branch ( cfe , s , g0 ) and
979- 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 ( )
980973 )
981974 }
982975
983976 /**
984977 * Holds if control flow node `cfn` only is reached when guard `g` evaluates to `v`,
985978 * because of an assertion.
986979 */
987- private predicate guardAssertionControlsNode ( Guard g , ControlFlow:: Node cfn , AbstractValue v ) {
988- exists ( Assertion a , Guard g0 , AbstractValue v0 |
989- asserts ( a , g0 , v0 ) and
990- impliesSteps ( g0 , v0 , g , v )
991- |
992- a .strictlyDominates ( cfn .getBasicBlock ( ) )
993- or
994- exists ( BasicBlock bb , int i , int j | bb .getNode ( i ) = a .getAControlFlowNode ( ) |
995- bb .getNode ( j ) = cfn and
996- j > i
997- )
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
998987 )
999988 }
1000989
@@ -1004,7 +993,7 @@ module Internal {
1004993 */
1005994 private predicate guardAssertionControlsElement ( Guard g , ControlFlowElement cfe , AbstractValue v ) {
1006995 forex ( ControlFlow:: Node cfn | cfn = cfe .getAControlFlowNode ( ) |
1007- guardAssertionControlsNode ( g , cfn , v )
996+ assertionControlsNodeInSameBasicBlock ( g , cfn , v )
1008997 )
1009998 }
1010999
@@ -1318,24 +1307,6 @@ module Internal {
13181307 )
13191308 }
13201309
1321- /**
1322- * Gets an expression that tests whether expression `e1` is equal to
1323- * expression `e2`.
1324- *
1325- * If the returned expression has abstract value `v`, then expression `e1` is
1326- * guaranteed to be equal to `e2`, and if the returned expression has abstract
1327- * value `v.getDualValue()`, then this expression is guaranteed to be
1328- * non-equal to `e`.
1329- *
1330- * For example, if the expression `x != ""` evaluates to `false` then the
1331- * expression `x` is guaranteed to be equal to `""`.
1332- */
1333- Expr getAnEqualityCheck ( Expr e1 , AbstractValue v , Expr e2 ) {
1334- result = getABooleanEqualityCheck ( e1 , v , e2 )
1335- or
1336- result = getAMatchingEqualityCheck ( e1 , v , e2 )
1337- }
1338-
13391310 private Expr getAnEqualityCheckVal ( Expr e , AbstractValue v , AbstractValue vExpr ) {
13401311 result = getAnEqualityCheck ( e , v , vExpr .getAnExpr ( ) )
13411312 }
@@ -1491,6 +1462,29 @@ module Internal {
14911462 not e = any ( LocalVariableDeclStmt s ) .getAVariableDeclExpr ( )
14921463 }
14931464
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+
14941488 cached
14951489 predicate isCustomNullCheck ( Call call , Expr arg , BooleanValue v , boolean isNull ) {
14961490 exists ( Callable callable , Parameter p |
@@ -1776,7 +1770,7 @@ module Internal {
17761770 exists ( Guard g | e = getAChildExprStar ( g ) |
17771771 guardControls ( g , bb , _)
17781772 or
1779- guardAssertionControlsNode ( g , bb .getANode ( ) , _)
1773+ assertionControlsNodeInSameBasicBlock ( g , bb .getANode ( ) , _)
17801774 )
17811775 }
17821776 }
@@ -1785,6 +1779,21 @@ module Internal {
17851779 private module Cached {
17861780 private import semmle.code.csharp.Caching
17871781
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+
17881797 pragma [ noinline]
17891798 private predicate isGuardedByNode0 (
17901799 ControlFlow:: Node cfn , AccessOrCallExpr guarded , Guard g , AccessOrCallExpr sub ,
@@ -1840,7 +1849,7 @@ module Internal {
18401849 ) {
18411850 isGuardedByNode0 ( guarded , _, g , sub , v )
18421851 or
1843- guardAssertionControlsNode ( g , guarded , v ) and
1852+ assertionControlsNodeInSameBasicBlock ( g , guarded , v ) and
18441853 exists ( ConditionOnExprComparisonConfig c | c .same ( sub , guarded .getElement ( ) ) )
18451854 }
18461855
0 commit comments