Semmle 1.21
Skip to end of metadata
Go to start of metadata

Name: Uncontrolled data in arithmetic expression

Description: Arithmetic operations on uncontrolled data that is not validated can cause overflows.

ID: cpp/uncontrolled-arithmetic

Kind: problem

Severity: warning

Precision: medium

Query: ArithmeticUncontrolled.ql
/**
 * @name Uncontrolled data in arithmetic expression
 * @description Arithmetic operations on uncontrolled data that is not
 *              validated can cause overflows.
 * @kind problem
 * @problem.severity warning
 * @precision medium
 * @id cpp/uncontrolled-arithmetic
 * @tags security
 *       external/cwe/cwe-190
 *       external/cwe/cwe-191
 */
import cpp

import semmle.code.cpp.security.Overflow
import semmle.code.cpp.security.Security
import semmle.code.cpp.security.TaintTracking

predicate isRandValue(Expr e) {
  e.(FunctionCall).getTarget().getName() = "rand" or
  exists(MacroInvocation mi |
    e = mi.getExpr() and
    e.getAChild*().(FunctionCall).getTarget().getName() = "rand"
  )
}

class SecurityOptionsArith extends SecurityOptions {
  override predicate isUserInput(Expr expr, string cause) {
    isRandValue(expr) and cause = "rand"
    and not expr.getParent*() instanceof DivExpr
  }
}

predicate taintedVarAccess(Expr origin, VariableAccess va) {
  isUserInput(origin, _) and
  tainted(origin, va)
}

/**
 * A value that undergoes division is likely to be bounded within a safe
 * range.
 */
predicate guardedByAssignDiv(Expr origin) {
  isUserInput(origin, _) and
  exists(AssignDivExpr div, VariableAccess va |
         tainted(origin, va) and div.getLValue() = va)
}

from Expr origin, Operation op, VariableAccess va, string effect
where taintedVarAccess(origin, va)
  and op.getAnOperand() = va
  and
  (
    (missingGuardAgainstUnderflow(op, va) and effect = "underflow") or
    (missingGuardAgainstOverflow(op, va) and effect = "overflow")
  )
  and not guardedByAssignDiv(origin)
select va, "$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".",
  origin, "Uncontrolled value"

Performing calculations on uncontrolled data can result in integer overflows unless the input is validated.

If the data is not under your control, and can take extremely large values, even arithmetic operations that would usually result in a small change in magnitude may result in overflows.

Recommendation

Always guard against overflow in arithmetic operations on uncontrolled data by doing one of the following:

  • Validate the data.
  • Define a guard on the arithmetic expression, so that the operation is performed only if the result can be known to be less than, or equal to, the maximum value for the type, for example INT_MAX.
  • Use a wider type, so that larger input values do not cause overflow.
Example

In this example, a random integer is generated. Because the value is not controlled by the programmer, it could be extremely large. Performing arithmetic operations on this value could therefore cause an overflow. To avoid this happening, the example shows how to perform a check before performing an arithmetic operation.

int main(int argc, char** argv) {
	int i = rand();
	// BAD: potential overflow
	int j = i + 1000;

	// ...

	int n = rand();
	int k;
	// GOOD: use a guard to prevent overflow
	if (n < INT_MAX-1000)
		k = n + 1000;
	else
		k = INT_MAX;
}

References
  • Common Weakness Enumeration: CWE-190.
  • Common Weakness Enumeration: CWE-191.