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

Name: Use of extreme values in arithmetic expression

Description: If a variable is assigned the maximum or minimum value for that variable's type and is then used in an arithmetic expression, this may result in an overflow.

ID: cpp/arithmetic-with-extreme-values

Kind: problem

Severity: warning

Precision: low

Query: ArithmeticWithExtremeValues.ql
/**
 * @name Use of extreme values in arithmetic expression
 * @description If a variable is assigned the maximum or minimum value
 *              for that variable's type and is then used in an
 *              arithmetic expression, this may result in an overflow.
 * @kind problem
 * @id cpp/arithmetic-with-extreme-values
 * @problem.severity warning
 * @precision low
 * @tags security
 *       reliability
 *       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 isMaxValue(Expr mie) {
  exists(MacroInvocation mi |
    mi.getExpr() = mie and
    (
      mi.getMacroName() = "CHAR_MAX" or
      mi.getMacroName() = "LLONG_MAX" or
      mi.getMacroName() = "INT_MAX" or
      mi.getMacroName() = "SHRT_MAX" or
      mi.getMacroName() = "UINT_MAX"
    )
  )
}

predicate isMinValue(Expr mie) {
  exists(MacroInvocation mi |
    mi.getExpr() = mie and
    (
      mi.getMacroName() = "CHAR_MIN" or
      mi.getMacroName() = "LLONG_MIN" or
      mi.getMacroName() = "INT_MIN" or
      mi.getMacroName() = "SHRT_MIN"
    )
  )
}

class SecurityOptionsArith extends SecurityOptions {
  override predicate isUserInput(Expr expr, string cause) {
    (isMaxValue(expr) and cause = "max value") or
    (isMinValue(expr) and cause = "min value")
  }
}

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

predicate causeEffectCorrespond(string cause, string effect) {
  (
    cause = "max value" and
    effect = "overflow"
  ) or (
    cause = "min value" and
    effect = "underflow"
  )
}

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

Assigning the maximum or minimum value for a type to a variable of that type and then using the variable in calculations may cause overflows.

Recommendation

Before using the variable, ensure that it is reassigned a value that does not cause an overflow, or use a wider type to do the arithmetic.

Example

In this example, assigning INT_MAX to a variable and adding one causes an overflow. However, casting to a long beforehand ensures that the arithmetic is done in the wider type, and so does not overflow.

int main(int argc, char** argv) {
	int i = INT_MAX;
	// BAD: overflow
	int j = i + 1;

	// ...

	int l = INT_MAX;
	// GOOD: no overflow
	long k = (long)l + 1;
}

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