ethereum / solidity

Solidity, the Smart Contract Programming Language
https://soliditylang.org
GNU General Public License v3.0
23.06k stars 5.71k forks source link

SMTChecker: doesn't recognize "OR" as arithmetic. #12959

Open drortirosh opened 2 years ago

drortirosh commented 2 years ago

The following sample is based on the standard "overflow" sample of the SMTChecker. There is an added "require" which makes sure the addition can never overflow - but the SMTChecker doesn't recognize it.

running the normal solc overflow.sol --model-checker-targets "underflow,overflow" --model-checker-engine all --model-checker-show-unproved Fails and claims that "Overflow can happen here" with parameter _y = 2**256 - 1

The SMT failed to see that checking an "OR'ed" value is equivalent to checking them separately (actually, I compare them to type(uint128).max, which mean I can even multiply them without overflow..

// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.8.0;

contract Overflow {
    uint immutable x;
    uint immutable y;

    function add(uint _x, uint _y) internal pure returns (uint) {
        return _x + _y;
    }

    constructor(uint _x, uint _y) {
        // added "require": this makes sure that both values are small enough, and are allowed to be added with no overflow
    require(  (_x | _y) < type(uint128).max );
        (x, y) = (_x, _y);
    }

    function stateAdd() public view returns (uint) {
        return add(x, y);
    }
}
leonardoalt commented 2 years ago

Hi @drortirosh , thanks for the issue!

The tool does in fact recognize the extra require, but:

It is unfortunate that such a small property becomes a complicated problem behind the scenes. If you switch the require to an arithmetic instead of a bitwise operation you might have better luck.