### In this space

##### Page tree
Semmle 1.21
Go to start of banner

# Multiplication result converted to larger type

Name: Multiplication result converted to larger type

Description: A multiplication result that is converted to a larger type can be a sign that the result can overflow the type converted from.

ID: cpp/integer-multiplication-cast-to-long

Kind: problem

Severity: warning

Precision: high

Query: IntMultToLong.ql
```/**
* @name Multiplication result converted to larger type
* @description A multiplication result that is converted to a larger type can
*              be a sign that the result can overflow the type converted from.
* @kind problem
* @problem.severity warning
* @precision high
* @id cpp/integer-multiplication-cast-to-long
* @tags reliability
*       security
*       correctness
*       types
*       external/cwe/cwe-190
*       external/cwe/cwe-192
*       external/cwe/cwe-197
*       external/cwe/cwe-681
*/
import cpp
import semmle.code.cpp.controlflow.SSA

/**
* Holds if `e` is either:
*  - a constant
*  - a char-typed expression, meaning it's a small number
*  - flows from one of the above
* In these cases the value of `e` is likely to be small and
* controlled, so we consider it less likely to cause an overflow.
*/
predicate likelySmall(Expr e) {
e.isConstant() or
e.getType().getSize() <= 1 or
e.(ArrayExpr).getArrayBase().getType().(ArrayType).getBaseType().isConst() or
def.getAUse(v) = e and
likelySmall(def.getDefiningValue(v))
)
}

/**
* Gets an operand of a multiply expression (we need the restriction
* to multiply expressions to get the correct transitive closure).
*/
Expr getMulOperand(MulExpr me) {
result = me.getAnOperand()
}

/**
* Gets the number of non-constant operands of a multiply expression,
* exploring into child multiply expressions rather than counting them
* as an operand directly.  For example the top level multiply here
* effectively has two non-constant operands:
* ```
*   (x * y) * 2
* ```
*/
int getEffectiveMulOperands(MulExpr me) {
result = count(Expr op |
op = getMulOperand*(me) and
not op instanceof MulExpr and
not likelySmall(op)
)
}

from MulExpr me, Type t1, Type t2
where t1 = me.getType().getUnderlyingType() and
t2 = me.getConversion().getType().getUnderlyingType() and
t1.getSize() < t2.getSize() and
(
(
t1.getUnspecifiedType() instanceof IntegralType and
t2.getUnspecifiedType() instanceof IntegralType
) or (
t1.getUnspecifiedType() instanceof FloatingPointType and
t2.getUnspecifiedType() instanceof FloatingPointType
)
) and

// exclude explicit conversions
me.getConversion().isCompilerGenerated() and

// require the multiply to have two non-constant operands
// (the intuition here is that multiplying two unknowns is
// much more likely to produce a result that needs significantly
// more bits than the operands did, and thus requires a larger
// type).
getEffectiveMulOperands(me) >= 2 and

// exclude varargs promotions
not exists(FunctionCall fc, int vararg |
fc.getArgument(vararg) = me and
vararg >= fc.getTarget().getNumberOfParameters()
) and

// exclude cases where the type was made bigger by a literal
// (compared to other cases such as assignment, this is more
// likely to be a trivial accident rather than suggesting a
// larger type is needed for the result).
not exists(Expr other, Expr e |
other = me.getParent().(BinaryOperation).getAnOperand() and
not other = me and
(
e = other or
e = other.(BinaryOperation).getAnOperand*()
) and
e.(Literal).getType().getSize() = t2.getSize()
)
select me, "Multiplication result may overflow '" + me.getType().toString() + "' before it is converted to '" + me.getFullyConverted().getType().toString() + "'."
```

This rule finds code that converts the result of an integer multiplication to a larger type. Since the conversion applies after the multiplication, arithmetic overflow may still occur.

The rule flags every multiplication of two non-constant integer expressions that is (explicitly or implicitly) converted to a larger integer type. The conversion is an indication that the expression would produce a result that would be too large to fit in the smaller integer type.

##### Recommendation

Use a cast to ensure that the multiplication is done using the larger integer type to avoid overflow.

##### Example

```int i = 2000000000;
long j = i * i; //Wrong: due to overflow on the multiplication between ints,
//will result to j being -1651507200, not 4000000000000000000

long k = (long) i * i; //Correct: the multiplication is done on longs instead of ints,
//and will not overflow
```