mirror of https://github.com/crytic/slither
commit
ee31aed5f9
@ -0,0 +1,71 @@ |
||||
""" |
||||
Module detecting constant functions |
||||
Recursively check the called functions |
||||
""" |
||||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification |
||||
from slither.formatters.attributes.const_functions import format |
||||
|
||||
|
||||
class ConstantFunctionsAsm(AbstractDetector): |
||||
""" |
||||
Constant function detector |
||||
""" |
||||
|
||||
ARGUMENT = 'constant-function' # run the detector with slither.py --ARGUMENT |
||||
HELP = 'Constant functions changing the state' # help information |
||||
IMPACT = DetectorClassification.MEDIUM |
||||
CONFIDENCE = DetectorClassification.MEDIUM |
||||
|
||||
WIKI = 'https://github.com/crytic/slither/wiki/Detector-Documentation#constant-functions-changing-the-state' |
||||
|
||||
WIKI_TITLE = 'Constant functions using assembly code' |
||||
WIKI_DESCRIPTION = ''' |
||||
Functions declared as `constant`/`pure`/`view` using assembly code. |
||||
|
||||
`constant`/`pure`/`view` was not enforced prior Solidity 0.5. |
||||
Starting from Solidity 0.5, a call to a `constant`/`pure`/`view` function uses the `STATICCALL` opcode, which reverts in case of state modification. |
||||
|
||||
As a result, a call to an [incorrectly labeled function may trap a contract compiled with Solidity 0.5](https://solidity.readthedocs.io/en/develop/050-breaking-changes.html#interoperability-with-older-contracts).''' |
||||
|
||||
WIKI_EXPLOIT_SCENARIO = ''' |
||||
```solidity |
||||
contract Constant{ |
||||
uint counter; |
||||
function get() public view returns(uint){ |
||||
counter = counter +1; |
||||
return counter |
||||
} |
||||
} |
||||
``` |
||||
`Constant` was deployed with Solidity 0.4.25. Bob writes a smart contract interacting with `Constant` in Solidity 0.5.0. |
||||
All the calls to `get` revert, breaking Bob's smart contract execution.''' |
||||
|
||||
WIKI_RECOMMENDATION = 'Ensure that the attributes of contracts compiled prior to Solidity 0.5.0 are correct.' |
||||
|
||||
def _detect(self): |
||||
""" Detect the constant function using assembly code |
||||
|
||||
Recursively visit the calls |
||||
Returns: |
||||
list: {'vuln', 'filename,'contract','func','#varsWritten'} |
||||
""" |
||||
results = [] |
||||
if self.slither.solc_version < "0.5.0": |
||||
for c in self.contracts: |
||||
for f in c.functions: |
||||
if f.contract_declarer != c: |
||||
continue |
||||
if f.view or f.pure: |
||||
if f.contains_assembly: |
||||
attr = 'view' if f.view else 'pure' |
||||
|
||||
info = [f, f' is declared {attr} but contains assembly code\n'] |
||||
res = self.generate_result(info, {'contains_assembly': True}) |
||||
|
||||
results.append(res) |
||||
|
||||
return results |
||||
|
||||
@staticmethod |
||||
def _format(slither, result): |
||||
format(slither, result) |
@ -1,79 +1,5 @@ |
||||
{ |
||||
"success": true, |
||||
"error": null, |
||||
"results": { |
||||
"detectors": [ |
||||
{ |
||||
"elements": [ |
||||
{ |
||||
"type": "function", |
||||
"name": "test_assembly_bug", |
||||
"source_mapping": { |
||||
"start": 185, |
||||
"length": 66, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/constant-0.5.1.sol", |
||||
"filename_relative": "tests/constant-0.5.1.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/constant-0.5.1.sol", |
||||
"filename_short": "tests/constant-0.5.1.sol", |
||||
"is_dependency": false, |
||||
"lines": [ |
||||
15, |
||||
16, |
||||
17 |
||||
], |
||||
"starting_column": 5, |
||||
"ending_column": 6 |
||||
}, |
||||
"type_specific_fields": { |
||||
"parent": { |
||||
"type": "contract", |
||||
"name": "Constant", |
||||
"source_mapping": { |
||||
"start": 0, |
||||
"length": 253, |
||||
"filename_used": "/home/travis/build/crytic/slither/tests/constant-0.5.1.sol", |
||||
"filename_relative": "tests/constant-0.5.1.sol", |
||||
"filename_absolute": "/home/travis/build/crytic/slither/tests/constant-0.5.1.sol", |
||||
"filename_short": "tests/constant-0.5.1.sol", |
||||
"is_dependency": false, |
||||
"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 |
||||
} |
||||
}, |
||||
"signature": "test_assembly_bug()" |
||||
} |
||||
} |
||||
], |
||||
"description": "Constant.test_assembly_bug() (tests/constant-0.5.1.sol#15-17) is declared view but contains assembly code\n", |
||||
"markdown": "[Constant.test_assembly_bug()](tests/constant-0.5.1.sol#L15-L17) is declared view but contains assembly code\n", |
||||
"id": "1f892cae08b89096bdc4d6ecdf55a3adc4b4314390e054fe2547d9c8e9f76e23", |
||||
"additional_fields": { |
||||
"contains_assembly": true |
||||
}, |
||||
"check": "constant-function", |
||||
"impact": "Medium", |
||||
"confidence": "Medium" |
||||
} |
||||
] |
||||
} |
||||
"results": null |
||||
} |
Loading…
Reference in new issue