@@ -42,6 +42,105 @@ class InterestingBinaryOverflowingExpr extends BinaryArithmeticOperation {
4242 )
4343 }
4444
45+ /**
46+ * Holds if there is a correct validity check after this expression which may overflow.
47+ */
48+ predicate hasValidPreCheck ( ) {
49+ exists ( GVN i1 , GVN i2 |
50+ i1 = globalValueNumber ( this .getLeftOperand ( ) ) and
51+ i2 = globalValueNumber ( this .getRightOperand ( ) )
52+ or
53+ i2 = globalValueNumber ( this .getLeftOperand ( ) ) and
54+ i1 = globalValueNumber ( this .getRightOperand ( ) )
55+ |
56+ // The CERT rule for signed integer overflow has a very specific pattern it recommends
57+ // for checking for overflow. We try to match the pattern here.
58+ // ((i2 > 0 && i1 > (INT_MAX - i2)) || (i2 < 0 && i1 < (INT_MIN - i2)))
59+ this instanceof AddExpr and
60+ exists ( LogicalOrExpr orExpr |
61+ // GuardCondition doesn't work in this case, so just confirm that this check dominates the overflow
62+ bbDominates ( orExpr .getBasicBlock ( ) , this .getBasicBlock ( ) ) and
63+ exists ( LogicalAndExpr andExpr |
64+ andExpr = orExpr .getAnOperand ( ) and
65+ exists ( StrictRelationalOperation gt |
66+ gt = andExpr .getAnOperand ( ) and
67+ gt .getLesserOperand ( ) .getValue ( ) = "0" and
68+ globalValueNumber ( gt .getGreaterOperand ( ) ) = i2
69+ ) and
70+ exists ( StrictRelationalOperation gt |
71+ gt = andExpr .getAnOperand ( ) and
72+ gt .getLesserOperand ( ) =
73+ any ( SubExpr se |
74+ se .getLeftOperand ( ) .getValue ( ) .toFloat ( ) = typeUpperBound ( getType ( ) ) and
75+ globalValueNumber ( se .getRightOperand ( ) ) = i2
76+ ) and
77+ globalValueNumber ( gt .getGreaterOperand ( ) ) = i1
78+ )
79+ ) and
80+ exists ( LogicalAndExpr andExpr |
81+ andExpr = orExpr .getAnOperand ( ) and
82+ exists ( StrictRelationalOperation gt |
83+ gt = andExpr .getAnOperand ( ) and
84+ gt .getGreaterOperand ( ) .getValue ( ) = "0" and
85+ globalValueNumber ( gt .getLesserOperand ( ) ) = i2
86+ ) and
87+ exists ( StrictRelationalOperation gt |
88+ gt = andExpr .getAnOperand ( ) and
89+ gt .getGreaterOperand ( ) =
90+ any ( SubExpr se |
91+ se .getLeftOperand ( ) .getValue ( ) .toFloat ( ) = typeLowerBound ( getType ( ) ) and
92+ globalValueNumber ( se .getRightOperand ( ) ) = i2
93+ ) and
94+ globalValueNumber ( gt .getLesserOperand ( ) ) = i1
95+ )
96+ )
97+ )
98+ or
99+ // The CERT rule for signed integer overflow has a very specific pattern it recommends
100+ // for checking for underflow. We try to match the pattern here.
101+ // ((i2 > 0 && i1 > (INT_MIN + i2)) || (i2 < 0 && i1 < (INT_MAX + i2)))
102+ this instanceof SubExpr and
103+ exists ( LogicalOrExpr orExpr |
104+ // GuardCondition doesn't work in this case, so just confirm that this check dominates the overflow
105+ bbDominates ( orExpr .getBasicBlock ( ) , this .getBasicBlock ( ) ) and
106+ exists ( LogicalAndExpr andExpr |
107+ andExpr = orExpr .getAnOperand ( ) and
108+ exists ( StrictRelationalOperation gt |
109+ gt = andExpr .getAnOperand ( ) and
110+ gt .getLesserOperand ( ) .getValue ( ) = "0" and
111+ globalValueNumber ( gt .getGreaterOperand ( ) ) = i2
112+ ) and
113+ exists ( StrictRelationalOperation gt |
114+ gt = andExpr .getAnOperand ( ) and
115+ gt .getGreaterOperand ( ) =
116+ any ( AddExpr se |
117+ se .getLeftOperand ( ) .getValue ( ) .toFloat ( ) = typeLowerBound ( getType ( ) ) and
118+ globalValueNumber ( se .getRightOperand ( ) ) = i2
119+ ) and
120+ globalValueNumber ( gt .getLesserOperand ( ) ) = i1
121+ )
122+ ) and
123+ exists ( LogicalAndExpr andExpr |
124+ andExpr = orExpr .getAnOperand ( ) and
125+ exists ( StrictRelationalOperation gt |
126+ gt = andExpr .getAnOperand ( ) and
127+ gt .getGreaterOperand ( ) .getValue ( ) = "0" and
128+ globalValueNumber ( gt .getLesserOperand ( ) ) = i2
129+ ) and
130+ exists ( StrictRelationalOperation gt |
131+ gt = andExpr .getAnOperand ( ) and
132+ gt .getLesserOperand ( ) =
133+ any ( AddExpr se |
134+ se .getLeftOperand ( ) .getValue ( ) .toFloat ( ) = typeUpperBound ( getType ( ) ) and
135+ globalValueNumber ( se .getRightOperand ( ) ) = i2
136+ ) and
137+ globalValueNumber ( gt .getGreaterOperand ( ) ) = i1
138+ )
139+ )
140+ )
141+ )
142+ }
143+
45144 /**
46145 * Holds if there is a correct validity check after this expression which may overflow.
47146 *
@@ -90,3 +189,7 @@ class InterestingBinaryOverflowingExpr extends BinaryArithmeticOperation {
90189 )
91190 }
92191}
192+
193+ private class StrictRelationalOperation extends RelationalOperation {
194+ StrictRelationalOperation ( ) { this .getOperator ( ) = [ ">" , "<" ] }
195+ }
0 commit comments