mirror of https://github.com/crytic/slither
- unchecked send - unchecked low level Add Internal/InternalDyanmicCall to unused return value detector Close 224pull/230/head
parent
30736c9f67
commit
9ba8bb8434
@ -0,0 +1,43 @@ |
||||
""" |
||||
Module detecting unused return values from low level |
||||
""" |
||||
from slither.detectors.abstract_detector import DetectorClassification |
||||
from .unused_return_values import UnusedReturnValues |
||||
from slither.slithir.operations import LowLevelCall |
||||
|
||||
class UncheckedLowLevel(UnusedReturnValues): |
||||
""" |
||||
If the return value of a send is not checked, it might lead to losing ether |
||||
""" |
||||
|
||||
ARGUMENT = 'unchecked-lowlevel' |
||||
HELP = 'Unchecked low-level calls' |
||||
IMPACT = DetectorClassification.MEDIUM |
||||
CONFIDENCE = DetectorClassification.MEDIUM |
||||
|
||||
WIKI = 'https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-low-level' |
||||
|
||||
WIKI_TITLE = 'Unchecked low-level calls' |
||||
WIKI_DESCRIPTION = 'The return value of a low-level call is not checked.' |
||||
WIKI_EXPLOIT_SCENARIO = ''' |
||||
```solidity |
||||
contract MyConc{ |
||||
function my_func(address payable dst) public payable{ |
||||
dst.call.value(msg.value)(""); |
||||
} |
||||
} |
||||
``` |
||||
The return value of the low-level call is not checked. As a result if the callfailed, the ether will be locked in the contract. |
||||
If the low level is used to prevent blocking operations, consider logging failed calls. |
||||
''' |
||||
|
||||
WIKI_RECOMMENDATION = 'Ensure that the return value of low-level call is checked or logged.' |
||||
|
||||
_txt_description = "low-level calls" |
||||
|
||||
def _is_instance(self, ir): |
||||
return isinstance(ir, LowLevelCall) |
||||
|
||||
|
||||
|
||||
|
@ -0,0 +1,40 @@ |
||||
""" |
||||
Module detecting unused return values from send |
||||
""" |
||||
|
||||
from slither.detectors.abstract_detector import DetectorClassification |
||||
from .unused_return_values import UnusedReturnValues |
||||
from slither.slithir.operations import Send |
||||
|
||||
class UncheckedSend(UnusedReturnValues): |
||||
""" |
||||
If the return value of a send is not checked, it might lead to losing ether |
||||
""" |
||||
|
||||
ARGUMENT = 'unchecked-send' |
||||
HELP = 'Unchecked send' |
||||
IMPACT = DetectorClassification.MEDIUM |
||||
CONFIDENCE = DetectorClassification.MEDIUM |
||||
|
||||
WIKI = 'https://github.com/crytic/slither/wiki/Detector-Documentation#unchecked-send' |
||||
|
||||
WIKI_TITLE = 'Unchecked Send' |
||||
WIKI_DESCRIPTION = 'The return value of a send is not checked.' |
||||
WIKI_EXPLOIT_SCENARIO = ''' |
||||
```solidity |
||||
contract MyConc{ |
||||
function my_func(address payable dst) public payable{ |
||||
dst.send(msg.value); |
||||
} |
||||
} |
||||
``` |
||||
The return value of `send` is not checked. As a result if the send failed, the ether will be locked in the contract. |
||||
If `send` is used to prevent blocking operations, consider logging the failed sent. |
||||
''' |
||||
|
||||
WIKI_RECOMMENDATION = 'Ensure that the return value of send is checked or logged.' |
||||
|
||||
_txt_description = "send calls" |
||||
|
||||
def _is_instance(self, ir): |
||||
return isinstance(ir, Send) |
@ -0,0 +1,73 @@ |
||||
[ |
||||
{ |
||||
"check": "unchecked-lowlevel", |
||||
"impact": "Medium", |
||||
"confidence": "Medium", |
||||
"description": "MyConc.bad (tests/unchecked_lowlevel-0.5.1.sol#2-4) does not use the value returned by low-level calls:\n\t-dst.call.value(msg.value)() (tests/unchecked_lowlevel-0.5.1.sol#3)\n", |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad", |
||||
"source_mapping": { |
||||
"start": 21, |
||||
"length": 96, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", |
||||
"filename_relative": "tests/unchecked_lowlevel-0.5.1.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", |
||||
"filename_short": "tests/unchecked_lowlevel-0.5.1.sol", |
||||
"lines": [ |
||||
2, |
||||
3, |
||||
4 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"contract": { |
||||
"type": "contract", |
||||
"name": "MyConc", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 274, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", |
||||
"filename_relative": "tests/unchecked_lowlevel-0.5.1.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", |
||||
"filename_short": "tests/unchecked_lowlevel-0.5.1.sol", |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "expression", |
||||
"expression": "dst.call.value(msg.value)()", |
||||
"source_mapping": { |
||||
"start": 81, |
||||
"length": 29, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", |
||||
"filename_relative": "tests/unchecked_lowlevel-0.5.1.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel-0.5.1.sol", |
||||
"filename_short": "tests/unchecked_lowlevel-0.5.1.sol", |
||||
"lines": [ |
||||
3 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 38 |
||||
} |
||||
} |
||||
] |
||||
} |
||||
] |
@ -0,0 +1,72 @@ |
||||
[ |
||||
{ |
||||
"check": "unchecked-lowlevel", |
||||
"impact": "Medium", |
||||
"confidence": "Medium", |
||||
"description": "MyConc.bad (tests/unchecked_lowlevel.sol#2-4) does not use the value returned by low-level calls:\n\t-dst.call.value(msg.value)() (tests/unchecked_lowlevel.sol#3)\n", |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad", |
||||
"source_mapping": { |
||||
"start": 21, |
||||
"length": 88, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", |
||||
"filename_relative": "tests/unchecked_lowlevel.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", |
||||
"filename_short": "tests/unchecked_lowlevel.sol", |
||||
"lines": [ |
||||
2, |
||||
3, |
||||
4 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"contract": { |
||||
"type": "contract", |
||||
"name": "MyConc", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 214, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", |
||||
"filename_relative": "tests/unchecked_lowlevel.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", |
||||
"filename_short": "tests/unchecked_lowlevel.sol", |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "expression", |
||||
"expression": "dst.call.value(msg.value)()", |
||||
"source_mapping": { |
||||
"start": 73, |
||||
"length": 29, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", |
||||
"filename_relative": "tests/unchecked_lowlevel.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_lowlevel.sol", |
||||
"filename_short": "tests/unchecked_lowlevel.sol", |
||||
"lines": [ |
||||
3 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 38 |
||||
} |
||||
} |
||||
] |
||||
} |
||||
] |
@ -0,0 +1,80 @@ |
||||
[ |
||||
{ |
||||
"check": "unchecked-send", |
||||
"impact": "Medium", |
||||
"confidence": "Medium", |
||||
"description": "MyConc.bad (tests/unchecked_send-0.5.1.sol#2-4) does not use the value returned by send calls:\n\t-dst.send(msg.value) (tests/unchecked_send-0.5.1.sol#3)\n", |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "bad", |
||||
"source_mapping": { |
||||
"start": 21, |
||||
"length": 86, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", |
||||
"filename_relative": "tests/unchecked_send-0.5.1.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", |
||||
"filename_short": "tests/unchecked_send-0.5.1.sol", |
||||
"lines": [ |
||||
2, |
||||
3, |
||||
4 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"contract": { |
||||
"type": "contract", |
||||
"name": "MyConc", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 419, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", |
||||
"filename_relative": "tests/unchecked_send-0.5.1.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", |
||||
"filename_short": "tests/unchecked_send-0.5.1.sol", |
||||
"lines": [ |
||||
1, |
||||
2, |
||||
3, |
||||
4, |
||||
5, |
||||
6, |
||||
7, |
||||
8, |
||||
9, |
||||
10, |
||||
11, |
||||
12, |
||||
13, |
||||
14, |
||||
15, |
||||
16, |
||||
17, |
||||
18 |
||||
], |
||||
"starting_column": 1, |
||||
"ending_column": 2 |
||||
} |
||||
} |
||||
}, |
||||
{ |
||||
"type": "expression", |
||||
"expression": "dst.send(msg.value)", |
||||
"source_mapping": { |
||||
"start": 81, |
||||
"length": 19, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", |
||||
"filename_relative": "tests/unchecked_send-0.5.1.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/unchecked_send-0.5.1.sol", |
||||
"filename_short": "tests/unchecked_send-0.5.1.sol", |
||||
"lines": [ |
||||
3 |
||||
], |
||||
"starting_column": 9, |
||||
"ending_column": 28 |
||||
} |
||||
} |
||||
] |
||||
} |
||||
] |
@ -0,0 +1,11 @@ |
||||
contract MyConc{ |
||||
function bad(address payable dst) external payable{ |
||||
dst.call.value(msg.value)(""); |
||||
} |
||||
|
||||
function good(address payable dst) external payable{ |
||||
(bool ret, bytes memory _) = dst.call.value(msg.value)(""); |
||||
require(ret); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,10 @@ |
||||
contract MyConc{ |
||||
function bad(address dst) external payable{ |
||||
dst.call.value(msg.value)(""); |
||||
} |
||||
|
||||
function good(address dst) external payable{ |
||||
require(dst.call.value(msg.value)()); |
||||
} |
||||
|
||||
} |
@ -0,0 +1,18 @@ |
||||
contract MyConc{ |
||||
function bad(address payable dst) external payable{ |
||||
dst.send(msg.value); |
||||
} |
||||
|
||||
function good(address payable dst) external payable{ |
||||
require(dst.send(msg.value)); |
||||
} |
||||
|
||||
function good2(address payable dst) external payable{ |
||||
bool res = dst.send(msg.value); |
||||
if(!res){ |
||||
emit Failed(dst, msg.value); |
||||
} |
||||
} |
||||
|
||||
event Failed(address, uint); |
||||
} |
Loading…
Reference in new issue