@@ -21,20 +21,13 @@ class InterestingOverflowingOperation extends Operation {
21
21
exprMightOverflowPositively ( this )
22
22
or
23
23
// Division and remainder are not handled by the library
24
- exists ( Expr leftOperand , Expr rightOperand |
25
- ( this instanceof DivExpr or this instanceof RemExpr ) and
26
- leftOperand = this .( BinaryOperation ) .getLeftOperand ( ) and
27
- rightOperand = this .( BinaryOperation ) .getRightOperand ( )
28
- or
29
- ( this instanceof AssignDivExpr or this instanceof AssignRemExpr ) and
30
- leftOperand = this .( AssignArithmeticOperation ) .getLValue ( ) and
31
- rightOperand = this .( AssignArithmeticOperation ) .getRValue ( )
32
- |
24
+ exists ( DivOrRemOperation divOrRem | divOrRem = this |
33
25
// The right hand side could be -1
34
- upperBound ( rightOperand ) >= - 1.0 and
35
- lowerBound ( rightOperand ) <= - 1.0 and
26
+ upperBound ( divOrRem . getDivisor ( ) ) >= - 1.0 and
27
+ lowerBound ( divOrRem . getDivisor ( ) ) <= - 1.0 and
36
28
// The left hand side could be the smallest possible integer value
37
- lowerBound ( leftOperand ) <= typeLowerBound ( leftOperand .getType ( ) .getUnderlyingType ( ) )
29
+ lowerBound ( divOrRem .getDividend ( ) ) <=
30
+ typeLowerBound ( divOrRem .getDividend ( ) .getType ( ) .getUnderlyingType ( ) )
38
31
)
39
32
) and
40
33
// Multiplication is not covered by the standard range analysis library, so implement our own
@@ -46,18 +39,6 @@ class InterestingOverflowingOperation extends Operation {
46
39
not this instanceof PointerArithmeticOperation
47
40
}
48
41
49
- /**
50
- * Get a `GVN` which guards this expression which may overflow.
51
- */
52
- GVN getAGuardingGVN ( ) {
53
- exists ( GuardCondition gc , Expr e |
54
- not gc = getABadOverflowCheck ( ) and
55
- TaintTracking:: localTaint ( DataFlow:: exprNode ( e ) , DataFlow:: exprNode ( gc .getAChild * ( ) ) ) and
56
- gc .controls ( this .getBasicBlock ( ) , _) and
57
- result = globalValueNumber ( e )
58
- )
59
- }
60
-
61
42
/**
62
43
* Holds if there is a correct validity check after this expression which may overflow.
63
44
*/
@@ -70,6 +51,27 @@ class InterestingOverflowingOperation extends Operation {
70
51
i1 = globalValueNumber ( op1 ) and
71
52
i2 = globalValueNumber ( op2 )
72
53
|
54
+ // For unsigned integer addition, look for this pattern:
55
+ // if (x + y > x)
56
+ // use(x + y)
57
+ // Ensuring it is not a bad overflow check
58
+ ( this instanceof AddExpr or this instanceof AssignAddExpr ) and
59
+ this .getType ( ) .getUnspecifiedType ( ) .( IntegralType ) .isUnsigned ( ) and
60
+ exists ( AddExpr ae , RelationalOperation relOp |
61
+ globalValueNumber ( relOp .getAnOperand ( ) ) = i1 and
62
+ relOp .getAnOperand ( ) = ae and
63
+ globalValueNumber ( ae .getAnOperand ( ) ) = i1 and
64
+ globalValueNumber ( ae .getAnOperand ( ) ) = i2
65
+ |
66
+ // At least one operand is not smaller than int
67
+ exists ( Expr op | op = ae .getAnOperand ( ) |
68
+ op .getType ( ) .getSize ( ) >= any ( IntType i ) .getSize ( )
69
+ )
70
+ or
71
+ // The result of the addition is explicitly converted to a smaller type before the comparison
72
+ ae .getExplicitlyConverted ( ) .getType ( ) .getSize ( ) < any ( IntType i ) .getSize ( )
73
+ )
74
+ or
73
75
// The CERT rule for signed integer overflow has a very specific pattern it recommends
74
76
// for checking for overflow. We try to match the pattern here.
75
77
// ((i2 > 0 && i1 > (INT_MAX - i2)) || (i2 < 0 && i1 < (INT_MIN - i2)))
@@ -156,6 +158,20 @@ class InterestingOverflowingOperation extends Operation {
156
158
)
157
159
)
158
160
or
161
+ // CERT recommends checking for divisor != -1 and dividor != INT_MIN
162
+ this instanceof DivOrRemOperation and
163
+ exists ( EqualityOperation eop |
164
+ // GuardCondition doesn't work in this case, so just confirm that this check dominates the overflow
165
+ globalValueNumber ( eop .getAnOperand ( ) ) = i1 and
166
+ eop .getAnOperand ( ) .getValue ( ) .toFloat ( ) =
167
+ typeLowerBound ( this .( DivOrRemOperation ) .getDividend ( ) .getType ( ) .getUnderlyingType ( ) )
168
+ ) and
169
+ exists ( EqualityOperation eop |
170
+ // GuardCondition doesn't work in this case, so just confirm that this check dominates the overflow
171
+ globalValueNumber ( eop .getAnOperand ( ) ) = i2 and
172
+ eop .getAnOperand ( ) .getValue ( ) .toInt ( ) = - 1
173
+ )
174
+ or
159
175
// The CERT rule for signed integer overflow has a very specific pattern it recommends
160
176
// for checking for multiplication underflow/overflow. We just use a heuristic here,
161
177
// which determines if at least 4 checks of the sort `a < INT_MAX / b` are present in the code.
@@ -193,36 +209,31 @@ class InterestingOverflowingOperation extends Operation {
193
209
)
194
210
)
195
211
}
196
-
197
- /**
198
- * Identifies a bad overflow check for this overflow expression.
199
- */
200
- GuardCondition getABadOverflowCheck ( ) {
201
- exists ( RelationalOperation relOp |
202
- ( this instanceof AddExpr or this instanceof AssignAddExpr ) and
203
- result = relOp and
204
- // Looking for this pattern:
205
- // if (x + y > x)
206
- // use(x + y)
207
- //
208
- globalValueNumber ( relOp .getAnOperand ( ) ) = globalValueNumber ( this ) and
209
- globalValueNumber ( relOp .getAnOperand ( ) ) = globalValueNumber ( this .getAnOperand ( ) )
210
- |
211
- // Signed overflow checks are insufficient
212
- this .getUnspecifiedType ( ) .( IntegralType ) .isSigned ( )
213
- or
214
- // Unsigned overflow checks can still be bad, if the result is promoted.
215
- forall ( Expr op | op = this .getAnOperand ( ) | op .getType ( ) .getSize ( ) < any ( IntType i ) .getSize ( ) ) and
216
- // Not explicitly converted to a smaller type before the comparison
217
- not this .getExplicitlyConverted ( ) .getType ( ) .getSize ( ) < any ( IntType i ) .getSize ( )
218
- )
219
- }
220
212
}
221
213
222
214
private class StrictRelationalOperation extends RelationalOperation {
223
215
StrictRelationalOperation ( ) { this .getOperator ( ) = [ ">" , "<" ] }
224
216
}
225
217
218
+ class DivOrRemOperation extends Operation {
219
+ DivOrRemOperation ( ) {
220
+ this instanceof DivExpr or
221
+ this instanceof RemExpr or
222
+ this instanceof AssignDivExpr or
223
+ this instanceof AssignRemExpr
224
+ }
225
+
226
+ Expr getDividend ( ) {
227
+ result = this .( BinaryOperation ) .getLeftOperand ( ) or
228
+ result = this .( AssignArithmeticOperation ) .getLValue ( )
229
+ }
230
+
231
+ Expr getDivisor ( ) {
232
+ result = this .( BinaryOperation ) .getRightOperand ( ) or
233
+ result = this .( AssignArithmeticOperation ) .getRValue ( )
234
+ }
235
+ }
236
+
226
237
/**
227
238
* Module inspired by the IntMultToLong.ql query.
228
239
*/
0 commit comments