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

[Bug-Candidate]: Crash when loading multiple definitions from another file's top-level #1116

Closed fiddlemath closed 2 years ago

fiddlemath commented 2 years ago

Describe the issue:

Slither crashes when run on our codebase.

Doing some test-case minimization suggests that it crashes as long as the following conditions are met:

A minimized example is attached.

Code example to reproduce the issue:

This requires two files, call them FreeFuns.sol and gnusto/Caller.sol. Caller being in a different directory that FreeFuns seems to be important.

In FreeFuns.sol:

function foo(uint256 x) pure returns (uint256) { return 0; }
function bar(uint256 x, uint256 y) pure returns (uint256) { return 0; }

In gnusto/Caller.sol:

import "../FreeFuns.sol" as Free;

contract Caller {
    function foo(uint256 x) public pure returns (uint256) {
        return Free.foo(x);
    }

    function bar(uint256 x, uint256 y) public pure returns (uint256) {
        return Free.bar(x, y);
    }
}

Version:

0.8.2, installed directly from github at commit f11d896.

Relevant log output:

❯ slither gnusto/Caller.sol
Compilation warnings/errors on gnusto/Caller.sol: Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: " to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information. --> gnusto/Caller.sol

Warning: SPDX license identifier not provided in source file. Before publishing, consider adding a comment containing "SPDX-License-Identifier: " to each source file. Use "SPDX-License-Identifier: UNLICENSED" for non-open-source code. Please see https://spdx.org for more information. --> FreeFuns.sol

Warning: Source file does not specify required compiler version! Consider adding "pragma solidity ^0.8.9;" --> FreeFuns.sol

Warning: Source file does not specify required compiler version! Consider adding "pragma solidity ^0.8.9;" --> gnusto/Caller.sol

Warning: Unused function parameter. Remove or comment out the variable name to silence this warning. --> FreeFuns.sol:1:14: | 1 | function foo(uint256 x) pure returns (uint256) { return 0; } | ^^^^^^^^^

Warning: Unused function parameter. Remove or comment out the variable name to silence this warning. --> FreeFuns.sol:2:14: | 2 | function bar(uint256 x, uint256 y) pure returns (uint256) { return 0; } | ^^^^^^^^^

Warning: Unused function parameter. Remove or comment out the variable name to silence this warning. --> FreeFuns.sol:2:25: | 2 | function bar(uint256 x, uint256 y) pure returns (uint256) { return 0; } | ^^^^^^^^^

Function not found foo Impossible to generate IR for Caller.foo Traceback (most recent call last): File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/main.py", line 744, in main_impl ) = process_all(filename, args, detector_classes, printer_classes) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/main.py", line 87, in process_all ) = process_single(compilation, args, detector_classes, printer_classes) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/main.py", line 70, in process_single slither = Slither(target, ast_format=ast, vars(args)) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slither.py", line 125, in init parser.analyze_contracts() File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 443, in analyze_contracts self._convert_to_slithir() File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 628, in _convert_to_slithir func.generate_slithir_and_analyze() File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/core/declarations/function.py", line 1708, in generate_slithir_and_analyze node.slithir_generation() File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/core/cfg/node.py", line 720, in slithir_generation self._irs = convert_expression(expression, self) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 118, in convert_expression result = apply_ir_heuristics(result, node) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 1737, in apply_ir_heuristics irs = propagate_type_and_convert_call(irs, node) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 430, in propagate_type_and_convert_call new_ins = propagate_types(ins, node) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 572, in propagate_types convert_type_of_high_and_internal_level_call(ir, function_contract) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 1468, in convert_type_of_high_and_internal_level_call func = _find_function_from_parameter(ir, candidates) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 256, in _find_function_from_parameter param = get_type(candidate.parameters[idx].type) IndexError: list index out of range None Error in gnusto/Caller.sol Traceback (most recent call last): File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/main.py", line 744, in main_impl ) = process_all(filename, args, detector_classes, printer_classes) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/main.py", line 87, in process_all ) = process_single(compilation, args, detector_classes, printer_classes) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/main.py", line 70, in process_single slither = Slither(target, ast_format=ast, vars(args)) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slither.py", line 125, in init parser.analyze_contracts() File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 443, in analyze_contracts self._convert_to_slithir() File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/solc_parsing/slither_compilation_unit_solc.py", line 628, in _convert_to_slithir func.generate_slithir_and_analyze() File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/core/declarations/function.py", line 1708, in generate_slithir_and_analyze node.slithir_generation() File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/core/cfg/node.py", line 720, in slithir_generation self._irs = convert_expression(expression, self) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 118, in convert_expression result = apply_ir_heuristics(result, node) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 1737, in apply_ir_heuristics irs = propagate_type_and_convert_call(irs, node) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 430, in propagate_type_and_convert_call new_ins = propagate_types(ins, node) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 572, in propagate_types convert_type_of_high_and_internal_level_call(ir, function_contract) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 1468, in convert_type_of_high_and_internal_level_call func = _find_function_from_parameter(ir, candidates) File "/Users/fiddle/.asdf/installs/python/3.9.2/lib/python3.9/site-packages/slither/slithir/convert.py", line 256, in _find_function_from_parameter param = get_type(candidate.parameters[idx].type) IndexError: list index out of range

fiddlemath commented 2 years ago

Notably, if we remove the bar declaration from Caller, slither doesn't crash, but its output contains:

Function not found foo
Impossible to generate IR for Caller.foo

If we remove the bar declarations from both Caller and FreeFuns, then slither seems to succeed.

montyly commented 2 years ago

Hi @fiddlemath. Thanks for reporting this issue, and creating a minimal PoC. We fixed it in #1130, the fix will be available in the next release (by the end of the month)