Skip to main content

Insecure Integer Arithmetic

Using Integer Arithmetic Securely

About Integer Overflows

What is an Integer Overflow?

Integer overflows are a type of vulnerability that occurs when the result of an arithmetic operation exceeds the range of values that can be represented by a particular data type, such as an integer.

In other words, an integer overflow occurs when the result of an operation is too large to be represented by the data type that stores it.

For example, if an integer data type is defined with a range of -128 to 127 and a program attempts to add 130 to a value of 127, an integer overflow will occur, and the value will "wrap around" to become -127. This can lead to unexpected and potentially dangerous behavior, such as crashes, incorrect calculation results, or security vulnerabilities.

Check out this video for a high-level explanation:

What is the impact of Integer Overflows?

Integer overflow vulnerabilities can be exploited by attackers to perform a variety of attacks, such as:

  • Buffer overflows: An integer overflow can be used to overwrite memory outside the bounds of an array, which can result in a buffer overflow vulnerability. This can allow an attacker to execute arbitrary code, modify data, or crash the program.
  • Denial-of-service (DoS) attacks: An integer overflow can be used to cause a program to consume excessive resources or crash, resulting in a DoS attack.
  • Logic bypasses: An integer overflow can be used to bypass security checks, such as input validation, authentication, or access control. This can allow an attacker to access unauthorized resources or perform actions that they are not authorized to perform.

How to prevent Integer Overflows?

To prevent integer overflow vulnerabilities, here are some best practices to follow:

  • Use appropriate data types: Use appropriate data types that can represent the range of values that are expected to be processed. For example, use a larger integer data type, such as a "long" instead of an "int", to avoid overflowing the range of values.
  • Bounds checking: Implement bounds checking to prevent arithmetic operations from exceeding the range of values that can be represented by a data type. This can involve checking the range of values before performing arithmetic operations or using libraries or tools that provide built-in checks.
  • Input validation: Validate all user input to ensure that it is of the expected data type and within the acceptable range of values. This can prevent attackers from manipulating input values to cause integer overflows.

References

Taxonomies

Training

An overflow/underflow happens when an arithmetic operation reaches the maximum or minimum size of a type. For instance, if a number is stored in the uint8 type, it means that the number is stored in an 8 bits unsigned number ranging from 0 to 2^8-1. In computer programming, an integer overflow occurs when an arithmetic operation attempts to create a numeric value that is outside of the range that can be represented with a given number of bits – either larger than the maximum or lower than the minimum representable value.

For Solidity contracts, this could mean that attackers could get extremely large amounts of tokens and/or manipulate other crypto-currencies as a result.

Category-specific references:

Option A: Adding Arithmetic Checks

  1. Go through the issues that GuardRails identified in the PR/MR

  2. Add the SafeMath library to your code

  3. Identify the code that looks like this:

    pragma solidity 0.4.24;

    contract OverflowVulnerableAndFixed {
    mapping (address => uint256) public balanceOf;
    // INSECURE
    function transfer(address _to, uint256 _value) public {
    /* Check if sender has balance */
    require(balanceOf[msg.sender] >= _value);
    /* Add and subtract new balances */
    balanceOf[msg.sender] -= _value;
    balanceOf[_to] += _value;
    }
    }
  4. Replace it with the following pattern:

    function transfer(address _to, uint256 _value) public {
    /* Check if sender has balance and for overflows */
    require(balanceOf[msg.sender] >= _value && balanceOf[_to] + _value >= balanceOf[_to]);
    /* Add and subtract new balances */
    balanceOf[msg.sender] -= _value;
    balanceOf[_to] += _value;
    }
  5. Test it

  6. Ship it 🚢 and relax 🌴

Option B: Using Safe Math Libraries

  1. Go through the issues that GuardRails identified in the PR/MR

  2. Add the SafeMath library to your code

  3. Identify the code that looks like this:

    uint256 amount = uint256(cnt) * _value;
  4. Use the SafeMath library like so:

    using SafeMath for uint256; // use SafeMath for uint256 variables
    // Change the previous line to this:
    uint256 amount = uint256(cnt).mul(_value);
  5. Test it

  6. Ship it 🚢 and relax 🌴