slither
slither copied to clipboard
[Bug]: convert_library_call is buggy and doesn't convert high level call/ set function properly
Describe the issue:
Slither with slither . --print echidna throws this error when the contract uses a library with fixed sized arrays.
Code example to reproduce the issue:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.10;
library Setter {
function set(
uint256[1] storage self,
uint256 key,
uint256 value
) internal {
self[key] = value;
}
}
contract SetterTest {
using Setter for uint256[1];
uint256[1] public params;
function f(uint256 key, uint256 value) external {
params.set(key, value);
}
}
Version:
$ slither --version
0.8.3
$ truffle version
Truffle v5.5.21 (core: 5.5.21)
Ganache v7.2.0
Solidity - 0.8.10 (solc-js)
Node v12.22.12
Web3.js v1.7.4
Relevant log output:
...
> Compiled successfully using:
- solc: 0.8.10+commit.fc410830.Emscripten.clang
Traceback (most recent call last):
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/__main__.py", line 744, in main_impl
) = process_all(filename, args, detector_classes, printer_classes)
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/__main__.py", line 87, in process_all
) = process_single(compilation, args, detector_classes, printer_classes)
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/__main__.py", line 72, in process_single
return _process(slither, detector_classes, printer_classes)
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/__main__.py", line 119, in _process
printer_results = slither.run_printers()
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/slither.py", line 211, in run_printers
return [p.output(self._crytic_compile.target).data for p in self._printers]
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/slither.py", line 211, in <listcomp>
return [p.output(self._crytic_compile.target).data for p in self._printers]
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/printers/guidance/echidna.py", line 380, in output
cst_functions = _extract_constant_functions(self.slither)
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/printers/guidance/echidna.py", line 118, in _extract_constant_functions
cst_functions = [_get_name(f) for f in contract.functions_entry_points if _is_constant(f)]
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/printers/guidance/echidna.py", line 118, in <listcomp>
cst_functions = [_get_name(f) for f in contract.functions_entry_points if _is_constant(f)]
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/printers/guidance/echidna.py", line 102, in _is_constant
if isinstance(ir.function, Variable) or ir.function.view or ir.function.pure:
AttributeError: 'NoneType' object has no attribute 'view'
None
Error in .
Traceback (most recent call last):
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/__main__.py", line 744, in main_impl
) = process_all(filename, args, detector_classes, printer_classes)
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/__main__.py", line 87, in process_all
) = process_single(compilation, args, detector_classes, printer_classes)
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/__main__.py", line 72, in process_single
return _process(slither, detector_classes, printer_classes)
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/__main__.py", line 119, in _process
printer_results = slither.run_printers()
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/slither.py", line 211, in run_printers
return [p.output(self._crytic_compile.target).data for p in self._printers]
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/slither.py", line 211, in <listcomp>
return [p.output(self._crytic_compile.target).data for p in self._printers]
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/printers/guidance/echidna.py", line 380, in output
cst_functions = _extract_constant_functions(self.slither)
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/printers/guidance/echidna.py", line 118, in _extract_constant_functions
cst_functions = [_get_name(f) for f in contract.functions_entry_points if _is_constant(f)]
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/printers/guidance/echidna.py", line 118, in <listcomp>
cst_functions = [_get_name(f) for f in contract.functions_entry_points if _is_constant(f)]
File "/home/deadcode/.local/lib/python3.10/site-packages/slither/printers/guidance/echidna.py", line 102, in _is_constant
if isinstance(ir.function, Variable) or ir.function.view or ir.function.pure:
AttributeError: 'NoneType' object has no attribute 'view'
Here, using_for can have keys that are objects and not strings:
https://github.com/crytic/slither/blob/ce9dbf650d7acfee51ddafd844929f4e8d345672/slither/slithir/convert.py#L529-L532
Thus, the high level call is not converted to a library call and the function attribute is not set, producing the following incorrect IR:
Contract Setter
Function Setter.set(uint256[1],uint256,uint256) (*)
Expression: self[key] = value
IRs:
REF_0(uint256) -> self[key]
REF_0 (->self) := value(uint256)
Contract SetterTest
Function SetterTest.f(uint256,uint256) (*)
Expression: params.set(key,value)
IRs:
TMP_0(None) = HIGH_LEVEL_CALL, dest:params(uint256[1]), function:set, arguments:['key', 'value']
EDIT:
The __eq__ function for ArrayType compares equality of its length property (which in this case is a Literal). The Literal class does not implement __eq__