@@ -17,6 +17,7 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
17
17
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
18
18
import semmle.code.cpp.controlflow.Guards
19
19
import semmle.code.cpp.ir.dataflow.DataFlow
20
+ import semmle.code.cpp.valuenumbering.GlobalValueNumbering
20
21
21
22
/**
22
23
* Holds if `sub` is guarded by a condition which ensures that
@@ -34,45 +35,108 @@ predicate isGuarded(SubExpr sub, Expr left, Expr right) {
34
35
}
35
36
36
37
/**
37
- * Holds if `n` is known or suspected to be less than or equal to
38
- * `sub.getLeftOperand() `.
38
+ * Gets an expression that is less than or equal to `sub.getLeftOperand()`.
39
+ * These serve as the base cases for `exprIsSubLeftOrLess `.
39
40
*/
40
- predicate exprIsSubLeftOrLess ( SubExpr sub , DataFlow :: Node n ) {
41
+ Expr exprIsLeftOrLessBase ( SubExpr sub ) {
41
42
interestingSubExpr ( sub , _) and // Manual magic
42
- (
43
- n .asExpr ( ) = sub .getLeftOperand ( )
43
+ exists ( Expr e | globalValueNumber ( e ) .getAnExpr ( ) = sub .getLeftOperand ( ) |
44
+ // sub = e - x
45
+ // result = e
46
+ // so:
47
+ // result <= e
48
+ result = e
49
+ or
50
+ // sub = e - x
51
+ // result = e & y
52
+ // so:
53
+ // result = e & y <= e
54
+ result .( BitwiseAndExpr ) .getAnOperand ( ) = e
44
55
or
45
- exists ( DataFlow:: Node other |
46
- // dataflow
47
- exprIsSubLeftOrLess ( sub , other ) and
48
- (
49
- DataFlow:: localFlowStep ( n , other ) or
50
- DataFlow:: localFlowStep ( other , n )
51
- )
56
+ exists ( SubExpr s |
57
+ // sub = e - x
58
+ // result = s
59
+ // s = e - y
60
+ // y >= 0
61
+ // so:
62
+ // result = e - y <= e
63
+ result = s and
64
+ s .getLeftOperand ( ) = e and
65
+ lowerBound ( s .getRightOperand ( ) .getFullyConverted ( ) ) >= 0
52
66
)
53
67
or
54
- exists ( DataFlow:: Node other |
55
- // guard constraining `sub`
56
- exprIsSubLeftOrLess ( sub , other ) and
57
- isGuarded ( sub , other .asExpr ( ) , n .asExpr ( ) ) // other >= n
68
+ exists ( Expr other |
69
+ // sub = e - x
70
+ // result = a
71
+ // a = e + y
72
+ // y <= 0
73
+ // so:
74
+ // result = e + y <= e + 0 = e
75
+ result .( AddExpr ) .hasOperands ( e , other ) and
76
+ upperBound ( other .getFullyConverted ( ) ) <= 0
58
77
)
59
78
or
60
- exists ( DataFlow:: Node other , float p , float q |
61
- // linear access of `other`
62
- exprIsSubLeftOrLess ( sub , other ) and
63
- linearAccess ( n .asExpr ( ) , other .asExpr ( ) , p , q ) and // n = p * other + q
64
- p <= 1 and
65
- q <= 0
79
+ exists ( DivExpr d |
80
+ // sub = e - x
81
+ // result = d
82
+ // d = e / y
83
+ // y >= 1
84
+ // so:
85
+ // result = e / y <= e / 1 = e
86
+ result = d and
87
+ d .getLeftOperand ( ) = e and
88
+ lowerBound ( d .getRightOperand ( ) .getFullyConverted ( ) ) >= 1
66
89
)
67
90
or
68
- exists ( DataFlow:: Node other , float p , float q |
69
- // linear access of `n`
70
- exprIsSubLeftOrLess ( sub , other ) and
71
- linearAccess ( other .asExpr ( ) , n .asExpr ( ) , p , q ) and // other = p * n + q
72
- p >= 1 and
73
- q >= 0
91
+ exists ( RShiftExpr rs |
92
+ // sub = e - x
93
+ // result = rs
94
+ // rs = e >> y
95
+ // so:
96
+ // result = e >> y <= e
97
+ result = rs and
98
+ rs .getLeftOperand ( ) = e
99
+ )
100
+ )
101
+ }
102
+
103
+ /**
104
+ * Holds if `n` is known or suspected to be less than or equal to
105
+ * `sub.getLeftOperand()`.
106
+ */
107
+ predicate exprIsSubLeftOrLess ( SubExpr sub , DataFlow:: Node n ) {
108
+ n .asExpr ( ) = exprIsLeftOrLessBase ( sub )
109
+ or
110
+ exists ( DataFlow:: Node other |
111
+ // dataflow
112
+ exprIsSubLeftOrLess ( sub , other ) and
113
+ (
114
+ DataFlow:: localFlowStep ( n , other ) or
115
+ DataFlow:: localFlowStep ( other , n )
74
116
)
75
117
)
118
+ or
119
+ exists ( DataFlow:: Node other |
120
+ // guard constraining `sub`
121
+ exprIsSubLeftOrLess ( sub , other ) and
122
+ isGuarded ( sub , other .asExpr ( ) , n .asExpr ( ) ) // other >= n
123
+ )
124
+ or
125
+ exists ( DataFlow:: Node other , float p , float q |
126
+ // linear access of `other`
127
+ exprIsSubLeftOrLess ( sub , other ) and
128
+ linearAccess ( n .asExpr ( ) , other .asExpr ( ) , p , q ) and // n = p * other + q
129
+ p <= 1 and
130
+ q <= 0
131
+ )
132
+ or
133
+ exists ( DataFlow:: Node other , float p , float q |
134
+ // linear access of `n`
135
+ exprIsSubLeftOrLess ( sub , other ) and
136
+ linearAccess ( other .asExpr ( ) , n .asExpr ( ) , p , q ) and // other = p * n + q
137
+ p >= 1 and
138
+ q >= 0
139
+ )
76
140
}
77
141
78
142
predicate interestingSubExpr ( SubExpr sub , RelationalOperation ro ) {
0 commit comments