Skip to content

Commit 1782a76

Browse files
committed
Merge branch 'dev' into restructure-test-folder
2 parents afeb77c + 0c174ef commit 1782a76

File tree

248 files changed

+1914
-343
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

248 files changed

+1914
-343
lines changed

slither/core/declarations/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,4 @@
1313
from .structure import Structure
1414
from .enum_contract import EnumContract
1515
from .structure_contract import StructureContract
16+
from .function_contract import FunctionContract

slither/core/declarations/contract.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,14 @@
2525
# pylint: disable=too-many-lines,too-many-instance-attributes,import-outside-toplevel,too-many-nested-blocks
2626
if TYPE_CHECKING:
2727
from slither.utils.type_helpers import LibraryCallType, HighLevelCallType, InternalCallType
28-
from slither.core.declarations import Enum, Event, Modifier, EnumContract, StructureContract
28+
from slither.core.declarations import (
29+
Enum,
30+
Event,
31+
Modifier,
32+
EnumContract,
33+
StructureContract,
34+
FunctionContract,
35+
)
2936
from slither.slithir.variables.variable import SlithIRVariable
3037
from slither.core.variables.variable import Variable
3138
from slither.core.variables.state_variable import StateVariable
@@ -56,7 +63,7 @@ def __init__(self):
5663
self._variables: Dict[str, "StateVariable"] = {}
5764
self._variables_ordered: List["StateVariable"] = []
5865
self._modifiers: Dict[str, "Modifier"] = {}
59-
self._functions: Dict[str, "Function"] = {}
66+
self._functions: Dict[str, "FunctionContract"] = {}
6067
self._linearizedBaseContracts = List[int]
6168

6269
# The only str is "*"
@@ -387,23 +394,23 @@ def functions_signatures_declared(self) -> List[str]:
387394
return self._signatures_declared
388395

389396
@property
390-
def functions(self) -> List["Function"]:
397+
def functions(self) -> List["FunctionContract"]:
391398
"""
392399
list(Function): List of the functions
393400
"""
394401
return list(self._functions.values())
395402

396-
def available_functions_as_dict(self) -> Dict[str, "Function"]:
403+
def available_functions_as_dict(self) -> Dict[str, "FunctionContract"]:
397404
if self._available_functions_as_dict is None:
398405
self._available_functions_as_dict = {
399406
f.full_name: f for f in self._functions.values() if not f.is_shadowed
400407
}
401408
return self._available_functions_as_dict
402409

403-
def add_function(self, func: "Function"):
410+
def add_function(self, func: "FunctionContract"):
404411
self._functions[func.canonical_name] = func
405412

406-
def set_functions(self, functions: Dict[str, "Function"]):
413+
def set_functions(self, functions: Dict[str, "FunctionContract"]):
407414
"""
408415
Set the functions
409416
@@ -413,21 +420,21 @@ def set_functions(self, functions: Dict[str, "Function"]):
413420
self._functions = functions
414421

415422
@property
416-
def functions_inherited(self) -> List["Function"]:
423+
def functions_inherited(self) -> List["FunctionContract"]:
417424
"""
418425
list(Function): List of the inherited functions
419426
"""
420427
return [f for f in self.functions if f.contract_declarer != self]
421428

422429
@property
423-
def functions_declared(self) -> List["Function"]:
430+
def functions_declared(self) -> List["FunctionContract"]:
424431
"""
425432
list(Function): List of the functions defined within the contract (not inherited)
426433
"""
427434
return [f for f in self.functions if f.contract_declarer == self]
428435

429436
@property
430-
def functions_entry_points(self) -> List["Function"]:
437+
def functions_entry_points(self) -> List["FunctionContract"]:
431438
"""
432439
list(Functions): List of public and external functions
433440
"""

slither/core/slither_core.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ def __init__(self):
9090

9191
self._show_ignored_findings = False
9292

93+
self.counter_slithir_tuple = 0
94+
self.counter_slithir_temporary = 0
95+
self.counter_slithir_reference = 0
96+
9397
###################################################################################
9498
###################################################################################
9599
# region Source code

slither/core/solidity_types/elementary_type.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,6 @@
8585
Max_Uint = {k: 2 ** (8 * i) - 1 if i > 0 else 2 ** 256 - 1 for i, k in enumerate(Uint)}
8686
Min_Uint = {k: 0 for k in Uint}
8787

88-
MaxValues = dict(Max_Int, **Max_Uint)
89-
MinValues = dict(Min_Int, **Min_Uint)
9088

9189
Byte = [
9290
"byte",
@@ -125,6 +123,16 @@
125123
"bytes32",
126124
]
127125

126+
Max_Byte = {k: 2 ** (8 * (i + 1)) - 1 for i, k in enumerate(Byte[2:])}
127+
Max_Byte["bytes"] = None
128+
Max_Byte["byte"] = 255
129+
Min_Byte = {k: 1 << (4 + 8 * i) for i, k in enumerate(Byte[2:])}
130+
Min_Byte["bytes"] = 0x0
131+
Min_Byte["byte"] = 0x10
132+
133+
MaxValues = dict(dict(Max_Int, **Max_Uint), **Max_Byte)
134+
MinValues = dict(dict(Min_Int, **Min_Uint), **Min_Byte)
135+
128136
# https://solidity.readthedocs.io/en/v0.4.24/types.html#fixed-point-numbers
129137
M = list(range(8, 257, 8))
130138
N = list(range(0, 81))

slither/detectors/all_detectors.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
from .statements.assembly import Assembly
2222
from .operations.low_level_calls import LowLevelCalls
2323
from .operations.unused_return_values import UnusedReturnValues
24+
from .operations.unchecked_transfer import UncheckedTransfer
2425
from .naming_convention.naming_convention import NamingConvention
2526
from .functions.external_function import ExternalFunction
2627
from .statements.controlled_delegatecall import ControlledDelegateCall

slither/detectors/operations/unchecked_low_level_return_values.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,5 @@ class UncheckedLowLevel(UnusedReturnValues):
3434

3535
WIKI_RECOMMENDATION = "Ensure that the return value of a low-level call is checked or logged."
3636

37-
_txt_description = "low-level calls"
38-
3937
def _is_instance(self, ir): # pylint: disable=no-self-use
4038
return isinstance(ir, LowLevelCall)

slither/detectors/operations/unchecked_send_return_value.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,5 @@ class UncheckedSend(UnusedReturnValues):
3535

3636
WIKI_RECOMMENDATION = "Ensure that the return value of `send` is checked or logged."
3737

38-
_txt_description = "send calls"
39-
4038
def _is_instance(self, ir): # pylint: disable=no-self-use
4139
return isinstance(ir, Send)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
Module detecting unused transfer/transferFrom return values from external calls
3+
"""
4+
5+
from slither.core.declarations import Function
6+
from slither.detectors.abstract_detector import DetectorClassification
7+
from slither.detectors.operations.unused_return_values import UnusedReturnValues
8+
from slither.slithir.operations import HighLevelCall
9+
10+
11+
class UncheckedTransfer(UnusedReturnValues):
12+
"""
13+
If the return value of a transfer/transferFrom function is never used, it's likely to be bug
14+
"""
15+
16+
ARGUMENT = "unchecked-transfer"
17+
HELP = "Unchecked tokens transfer"
18+
IMPACT = DetectorClassification.HIGH
19+
CONFIDENCE = DetectorClassification.MEDIUM
20+
21+
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-transfer"
22+
23+
WIKI_TITLE = "Unchecked transfer"
24+
WIKI_DESCRIPTION = "The return value of an external transfer/transferFrom call is not checked"
25+
WIKI_EXPLOIT_SCENARIO = """
26+
```solidity
27+
contract Token {
28+
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
29+
}
30+
contract MyBank{
31+
mapping(address => uint) balances;
32+
Token token;
33+
function deposit(uint amount) public{
34+
token.transferFrom(msg.sender, address(this), amount);
35+
balances[msg.sender] += amount;
36+
}
37+
}
38+
```
39+
Several tokens do not revert in case of failure and return false. If one of these tokens is used in `MyBank`, `deposit` will not revert if the transfer fails, and an attacker can call `deposit` for free.."""
40+
41+
WIKI_RECOMMENDATION = (
42+
"Use `SafeERC20`, or ensure that the transfer/transferFrom return value is checked."
43+
)
44+
45+
def _is_instance(self, ir): # pylint: disable=no-self-use
46+
return (
47+
isinstance(ir, HighLevelCall)
48+
and isinstance(ir.function, Function)
49+
and ir.function.solidity_signature
50+
in ["transfer(address,uint256)", "transferFrom(address,address,uint256)"]
51+
)

slither/detectors/operations/unused_return_values.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from slither.core.variables.state_variable import StateVariable
66
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification
77
from slither.slithir.operations import HighLevelCall
8+
from slither.core.declarations import Function
89

910

1011
class UnusedReturnValues(AbstractDetector):
@@ -36,10 +37,15 @@ class UnusedReturnValues(AbstractDetector):
3637

3738
WIKI_RECOMMENDATION = "Ensure that all the return values of the function calls are used."
3839

39-
_txt_description = "external calls"
40-
4140
def _is_instance(self, ir): # pylint: disable=no-self-use
42-
return isinstance(ir, HighLevelCall)
41+
return isinstance(ir, HighLevelCall) and (
42+
(
43+
isinstance(ir.function, Function)
44+
and ir.function.solidity_signature
45+
not in ["transfer(address,uint256)", "transferFrom(address,address,uint256)"]
46+
)
47+
or not isinstance(ir.function, Function)
48+
)
4349

4450
def detect_unused_return_values(self, f): # pylint: disable=no-self-use
4551
"""

0 commit comments

Comments
 (0)