crytic / slither

Static Analyzer for Solidity and Vyper
https://blog.trailofbits.com/2018/10/19/slither-a-solidity-static-analysis-framework/
GNU Affero General Public License v3.0
5.34k stars 970 forks source link

create reference variable for offset and length in Yul #1469

Open eMarchenko opened 2 years ago

eMarchenko commented 2 years ago

Describe the issue:

write-after-write detector falsely reacts on assembly work with calldata:

Code example to reproduce the issue:

function foo(bytes calldata cd) private pure returns (bytes calldata signature)
{
    assembly {
        let ptr := add(cd.offset, calldataload(cd.offset))
        signature.offset := add(ptr, 0x20)
        signature.length := calldataload(ptr)
    }
}

Version:

^0.9 - tool was run on other machine

Relevant log output:

No response

0xalpharush commented 2 years ago

It looks like the IR doesn't currently create a reference to each member of signature, offset and length. This would need to be added to eliminate this false positive.

Contract Test
    Function Test.foo(bytes) (*)
        Expression: ptr_foo_asm_0 = cd + calldataload(uint256)(cd)
        IRs:
            TMP_0(uint256) = SOLIDITY_CALL calldataload(uint256)(cd)
            TMP_1(bytes) = cd + TMP_0
            ptr_foo_asm_0(uint256) := TMP_1(bytes)
        Expression: signature = ptr_foo_asm_0 + 0x20
        IRs:
            TMP_2(uint256) = ptr_foo_asm_0 + 32
            signature(bytes) := TMP_2(uint256)
        Expression: signature = calldataload(uint256)(ptr_foo_asm_0)
        IRs:
            TMP_3(uint256) = SOLIDITY_CALL calldataload(uint256)(ptr_foo_asm_0)
            signature(bytes) := TMP_3(uint256)

foo.sol analyzed (1 contracts)