@@ -64,6 +64,32 @@ int getEffectiveMulOperands(MulExpr me) {
6464 )
6565}
6666
67+ class LeafExpr extends Expr {
68+ LeafExpr ( ) { not this instanceof BinaryOperation }
69+ }
70+
71+ /**
72+ * Gets the size of the largest type (in bytes) of an non-literal
73+ * operand to a binary operation. For example, for
74+ * ```
75+ * unsigned char a; short b;
76+ * (a + 1) * b;
77+ * ```
78+ * the result is 2 (i.e., the size of a `short`)
79+ */
80+ int widenedFromLiteralFromSize ( Expr e ) {
81+ exists ( Literal lit |
82+ lit = e .( BinaryOperation ) .getAnOperand + ( ) and
83+ result = max ( LeafExpr other |
84+ other = e .( BinaryOperation ) .getAnOperand + ( ) and
85+ not other instanceof Literal
86+ |
87+ other .getType ( ) .getSize ( )
88+ ) and
89+ result < lit .getType ( ) .getSize ( )
90+ )
91+ }
92+
6793from MulExpr me , Type t1 , Type t2
6894where
6995 t1 = me .getType ( ) .getUnderlyingType ( ) and
@@ -101,6 +127,20 @@ where
101127 e = other .( BinaryOperation ) .getAnOperand * ( )
102128 ) and
103129 e .( Literal ) .getType ( ) .getSize ( ) = t2 .getSize ( )
130+ ) and
131+ // exclude cases where the operands to the multiplication were
132+ // small, but widened due to a literal in a subexpression.
133+ // For instance, if the multiplication is
134+ // ```
135+ // int c = (a + 1) * (b + 1)
136+ // ```
137+ // where a and b are both unsigned chars. In this case the maximum
138+ // value of c will be 256 * 256, even though the arguments to the
139+ // multiplication are both typed as int.
140+ not exists ( Expr e1 , Expr e2 |
141+ e1 = me .getLeftOperand ( ) and
142+ e2 = me .getRightOperand ( ) and
143+ widenedFromLiteralFromSize ( e1 ) + widenedFromLiteralFromSize ( e2 ) < t1 .getSize ( )
104144 )
105145select me ,
106146 "Multiplication result may overflow '" + me .getType ( ) .toString ( ) + "' before it is converted to '"
0 commit comments