-
Notifications
You must be signed in to change notification settings - Fork 982
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #838 from crytic/dev-dead-code
Open source dead-code detector
- Loading branch information
Showing
7 changed files
with
337 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
""" | ||
Module detecting dead code | ||
""" | ||
from typing import List, Tuple | ||
|
||
from slither.core.declarations import Function, FunctionContract, Contract | ||
from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification | ||
|
||
|
||
class DeadCode(AbstractDetector): | ||
""" | ||
Unprotected function detector | ||
""" | ||
|
||
ARGUMENT = "dead-code" | ||
HELP = "Functions that are not used" | ||
IMPACT = DetectorClassification.INFORMATIONAL | ||
CONFIDENCE = DetectorClassification.MEDIUM | ||
|
||
WIKI = "https://github.com/crytic/slither/wiki/Detector-Documentation#dead-code" | ||
|
||
WIKI_TITLE = "Dead-code" | ||
WIKI_DESCRIPTION = "Functions that are not sued." | ||
WIKI_EXPLOIT_SCENARIO = """ | ||
```solidity | ||
contract Contract{ | ||
function dead_code() internal() {} | ||
} | ||
``` | ||
`dead_code` is not used in the contract, and make the code's review more difficult.""" | ||
|
||
WIKI_RECOMMENDATION = "Remove unused functions." | ||
|
||
def _detect(self): | ||
|
||
results = [] | ||
|
||
functions_used = set() | ||
for contract in self.compilation_unit.contracts_derived: | ||
all_functionss_called = [ | ||
f.all_internal_calls() for f in contract.functions_entry_points | ||
] | ||
all_functions_called = [item for sublist in all_functionss_called for item in sublist] | ||
functions_used |= { | ||
f.canonical_name for f in all_functions_called if isinstance(f, Function) | ||
} | ||
all_libss_called = [f.all_library_calls() for f in contract.functions_entry_points] | ||
all_libs_called: List[Tuple[Contract, Function]] = [ | ||
item for sublist in all_libss_called for item in sublist | ||
] | ||
functions_used |= { | ||
lib[1].canonical_name for lib in all_libs_called if isinstance(lib, tuple) | ||
} | ||
for function in sorted(self.compilation_unit.functions, key=lambda x: x.canonical_name): | ||
if ( | ||
function.visibility in ["public", "external"] | ||
or function.is_constructor | ||
or function.is_fallback | ||
or function.is_constructor_variables | ||
): | ||
continue | ||
if function.canonical_name in functions_used: | ||
continue | ||
if isinstance(function, FunctionContract) and ( | ||
function.contract_declarer.is_from_dependency() | ||
): | ||
continue | ||
info = [function, " is never used and should be removed\n"] | ||
res = self.generate_result(info) | ||
results.append(res) | ||
|
||
return results |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
contract Test{ | ||
function unused() internal{ | ||
|
||
} | ||
} | ||
|
||
|
||
contract Test2{ | ||
|
||
function unused_but_shadowed() internal virtual{ | ||
|
||
} | ||
} | ||
|
||
contract Test3 is Test2{ | ||
function unused_but_shadowed() internal override{ | ||
|
||
} | ||
|
||
function f() public{ | ||
unused_but_shadowed(); | ||
} | ||
} | ||
|
||
contract Test4 is Test2{ | ||
function unused_but_shadowed() internal override{ | ||
|
||
} | ||
} |
173 changes: 173 additions & 0 deletions
173
tests/detectors/dead-code/0.8.0/dead-code.sol.0.8.0.DeadCode.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
[ | ||
[ | ||
{ | ||
"elements": [ | ||
{ | ||
"type": "function", | ||
"name": "unused", | ||
"source_mapping": { | ||
"start": 19, | ||
"length": 34, | ||
"filename_used": "/GENERIC_PATH", | ||
"filename_relative": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"filename_absolute": "/GENERIC_PATH", | ||
"filename_short": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"is_dependency": false, | ||
"lines": [ | ||
2, | ||
3, | ||
4 | ||
], | ||
"starting_column": 5, | ||
"ending_column": 6 | ||
}, | ||
"type_specific_fields": { | ||
"parent": { | ||
"type": "contract", | ||
"name": "Test", | ||
"source_mapping": { | ||
"start": 0, | ||
"length": 55, | ||
"filename_used": "/GENERIC_PATH", | ||
"filename_relative": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"filename_absolute": "/GENERIC_PATH", | ||
"filename_short": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"is_dependency": false, | ||
"lines": [ | ||
1, | ||
2, | ||
3, | ||
4, | ||
5 | ||
], | ||
"starting_column": 1, | ||
"ending_column": 2 | ||
} | ||
}, | ||
"signature": "unused()" | ||
} | ||
} | ||
], | ||
"description": "Test.unused() (tests/detectors/dead-code/0.8.0/dead-code.sol#2-4) is never used and should be removed\n", | ||
"markdown": "[Test.unused()](tests/detectors/dead-code/0.8.0/dead-code.sol#L2-L4) is never used and should be removed\n", | ||
"first_markdown_element": "tests/detectors/dead-code/0.8.0/dead-code.sol#L2-L4", | ||
"id": "a7c13823116566bbbbb68e8a7efa78fe64785fcb8582069373eda7f27c523cb3", | ||
"check": "dead-code", | ||
"impact": "Informational", | ||
"confidence": "Medium" | ||
}, | ||
{ | ||
"elements": [ | ||
{ | ||
"type": "function", | ||
"name": "unused_but_shadowed", | ||
"source_mapping": { | ||
"start": 79, | ||
"length": 55, | ||
"filename_used": "/GENERIC_PATH", | ||
"filename_relative": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"filename_absolute": "/GENERIC_PATH", | ||
"filename_short": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"is_dependency": false, | ||
"lines": [ | ||
10, | ||
11, | ||
12 | ||
], | ||
"starting_column": 5, | ||
"ending_column": 6 | ||
}, | ||
"type_specific_fields": { | ||
"parent": { | ||
"type": "contract", | ||
"name": "Test2", | ||
"source_mapping": { | ||
"start": 58, | ||
"length": 78, | ||
"filename_used": "/GENERIC_PATH", | ||
"filename_relative": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"filename_absolute": "/GENERIC_PATH", | ||
"filename_short": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"is_dependency": false, | ||
"lines": [ | ||
8, | ||
9, | ||
10, | ||
11, | ||
12, | ||
13 | ||
], | ||
"starting_column": 1, | ||
"ending_column": 2 | ||
} | ||
}, | ||
"signature": "unused_but_shadowed()" | ||
} | ||
} | ||
], | ||
"description": "Test2.unused_but_shadowed() (tests/detectors/dead-code/0.8.0/dead-code.sol#10-12) is never used and should be removed\n", | ||
"markdown": "[Test2.unused_but_shadowed()](tests/detectors/dead-code/0.8.0/dead-code.sol#L10-L12) is never used and should be removed\n", | ||
"first_markdown_element": "tests/detectors/dead-code/0.8.0/dead-code.sol#L10-L12", | ||
"id": "aaba496684b73955e90b555de174e1cd03f0fee337849c4d58c10ef76ff93582", | ||
"check": "dead-code", | ||
"impact": "Informational", | ||
"confidence": "Medium" | ||
}, | ||
{ | ||
"elements": [ | ||
{ | ||
"type": "function", | ||
"name": "unused_but_shadowed", | ||
"source_mapping": { | ||
"start": 319, | ||
"length": 56, | ||
"filename_used": "/GENERIC_PATH", | ||
"filename_relative": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"filename_absolute": "/GENERIC_PATH", | ||
"filename_short": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"is_dependency": false, | ||
"lines": [ | ||
26, | ||
27, | ||
28 | ||
], | ||
"starting_column": 5, | ||
"ending_column": 6 | ||
}, | ||
"type_specific_fields": { | ||
"parent": { | ||
"type": "contract", | ||
"name": "Test4", | ||
"source_mapping": { | ||
"start": 290, | ||
"length": 87, | ||
"filename_used": "/GENERIC_PATH", | ||
"filename_relative": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"filename_absolute": "/GENERIC_PATH", | ||
"filename_short": "tests/detectors/dead-code/0.8.0/dead-code.sol", | ||
"is_dependency": false, | ||
"lines": [ | ||
25, | ||
26, | ||
27, | ||
28, | ||
29 | ||
], | ||
"starting_column": 1, | ||
"ending_column": 2 | ||
} | ||
}, | ||
"signature": "unused_but_shadowed()" | ||
} | ||
} | ||
], | ||
"description": "Test4.unused_but_shadowed() (tests/detectors/dead-code/0.8.0/dead-code.sol#26-28) is never used and should be removed\n", | ||
"markdown": "[Test4.unused_but_shadowed()](tests/detectors/dead-code/0.8.0/dead-code.sol#L26-L28) is never used and should be removed\n", | ||
"first_markdown_element": "tests/detectors/dead-code/0.8.0/dead-code.sol#L26-L28", | ||
"id": "74ea8421cf7fa9e04d243014b61f3eee7a9c7648df98316c3881dd4f1f2ab3f7", | ||
"check": "dead-code", | ||
"impact": "Informational", | ||
"confidence": "Medium" | ||
} | ||
] | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters