crytic/slither

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

fiddlemath opened this issue · 2 comments

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:

  • One file imports another's top-level declarations, in the form import "../File.sol" as Foo
  • The declaration-exporting file contains at least two top-level declarations, with parameters

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

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.

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)