@@ -21,20 +21,13 @@ class InterestingOverflowingOperation extends Operation {
2121 exprMightOverflowPositively ( this )
2222 or
2323 // 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 |
3325 // 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
3628 // 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 ( ) )
3831 )
3932 ) and
4033 // Multiplication is not covered by the standard range analysis library, so implement our own
@@ -46,18 +39,6 @@ class InterestingOverflowingOperation extends Operation {
4639 not this instanceof PointerArithmeticOperation
4740 }
4841
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-
6142 /**
6243 * Holds if there is a correct validity check after this expression which may overflow.
6344 */
@@ -70,6 +51,27 @@ class InterestingOverflowingOperation extends Operation {
7051 i1 = globalValueNumber ( op1 ) and
7152 i2 = globalValueNumber ( op2 )
7253 |
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
7375 // The CERT rule for signed integer overflow has a very specific pattern it recommends
7476 // for checking for overflow. We try to match the pattern here.
7577 // ((i2 > 0 && i1 > (INT_MAX - i2)) || (i2 < 0 && i1 < (INT_MIN - i2)))
@@ -156,6 +158,20 @@ class InterestingOverflowingOperation extends Operation {
156158 )
157159 )
158160 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
159175 // The CERT rule for signed integer overflow has a very specific pattern it recommends
160176 // for checking for multiplication underflow/overflow. We just use a heuristic here,
161177 // 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 {
193209 )
194210 )
195211 }
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- }
220212}
221213
222214private class StrictRelationalOperation extends RelationalOperation {
223215 StrictRelationalOperation ( ) { this .getOperator ( ) = [ ">" , "<" ] }
224216}
225217
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+
226237/**
227238 * Module inspired by the IntMultToLong.ql query.
228239 */
0 commit comments