mirror of https://github.com/crytic/slither
parent
1fb652fbb8
commit
243e162c93
@ -0,0 +1,3 @@ |
|||||||
|
contract C{ |
||||||
|
|
||||||
|
} |
@ -0,0 +1,262 @@ |
|||||||
|
import json |
||||||
|
import os |
||||||
|
import pathlib |
||||||
|
import sys |
||||||
|
from pprint import pprint |
||||||
|
from typing import Type |
||||||
|
|
||||||
|
import pytest |
||||||
|
from deepdiff import DeepDiff # pip install deepdiff |
||||||
|
|
||||||
|
from slither import Slither |
||||||
|
from slither.detectors.abstract_detector import AbstractDetector |
||||||
|
from slither.detectors.attributes.const_functions_asm import ConstantFunctionsAsm |
||||||
|
from slither.detectors.attributes.const_functions_state import ConstantFunctionsState |
||||||
|
from slither.detectors.attributes.constant_pragma import ConstantPragma |
||||||
|
from slither.detectors.attributes.incorrect_solc import IncorrectSolc |
||||||
|
from slither.detectors.attributes.locked_ether import LockedEther |
||||||
|
from slither.detectors.erc.incorrect_erc20_interface import IncorrectERC20InterfaceDetection |
||||||
|
from slither.detectors.erc.incorrect_erc721_interface import IncorrectERC721InterfaceDetection |
||||||
|
from slither.detectors.erc.unindexed_event_parameters import UnindexedERC20EventParameters |
||||||
|
from slither.detectors.examples.backdoor import Backdoor |
||||||
|
from slither.detectors.functions.arbitrary_send import ArbitrarySend |
||||||
|
from slither.detectors.functions.external_function import ExternalFunction |
||||||
|
from slither.detectors.functions.suicidal import Suicidal |
||||||
|
from slither.detectors.naming_convention.naming_convention import NamingConvention |
||||||
|
from slither.detectors.operations.block_timestamp import Timestamp |
||||||
|
from slither.detectors.operations.low_level_calls import LowLevelCalls |
||||||
|
from slither.detectors.operations.unchecked_low_level_return_values import UncheckedLowLevel |
||||||
|
from slither.detectors.operations.unchecked_send_return_value import UncheckedSend |
||||||
|
from slither.detectors.operations.unused_return_values import UnusedReturnValues |
||||||
|
from slither.detectors.operations.void_constructor import VoidConstructor |
||||||
|
from slither.detectors.reentrancy.reentrancy_eth import ReentrancyEth |
||||||
|
from slither.detectors.reentrancy.reentrancy_events import ReentrancyEvent |
||||||
|
from slither.detectors.shadowing.abstract import ShadowingAbstractDetection |
||||||
|
from slither.detectors.shadowing.builtin_symbols import BuiltinSymbolShadowing |
||||||
|
from slither.detectors.shadowing.local import LocalShadowing |
||||||
|
from slither.detectors.shadowing.state import StateShadowing |
||||||
|
from slither.detectors.source.rtlo import RightToLeftOverride |
||||||
|
from slither.detectors.statements.assembly import Assembly |
||||||
|
from slither.detectors.statements.calls_in_loop import MultipleCallsInLoop |
||||||
|
from slither.detectors.statements.controlled_delegatecall import ControlledDelegateCall |
||||||
|
from slither.detectors.statements.incorrect_strict_equality import IncorrectStrictEquality |
||||||
|
from slither.detectors.statements.too_many_digits import TooManyDigits |
||||||
|
from slither.detectors.statements.tx_origin import TxOrigin |
||||||
|
from slither.detectors.variables.possible_const_state_variables import ConstCandidateStateVars |
||||||
|
from slither.detectors.variables.uninitialized_local_variables import UninitializedLocalVars |
||||||
|
from slither.detectors.variables.uninitialized_state_variables import ( |
||||||
|
UninitializedStateVarsDetection, |
||||||
|
) |
||||||
|
from slither.detectors.variables.uninitialized_storage_variables import UninitializedStorageVars |
||||||
|
from slither.detectors.variables.unused_state_variables import UnusedStateVars |
||||||
|
|
||||||
|
|
||||||
|
class Test: # pylint: disable=too-few-public-methods |
||||||
|
def __init__(self, detector: Type[AbstractDetector], test_file: str, solc_ver: str): |
||||||
|
self.detector = detector |
||||||
|
self.test_file = test_file |
||||||
|
self.expected_result = test_file + "." + solc_ver + "." + detector.__name__ + ".json" |
||||||
|
self.solc_ver = solc_ver |
||||||
|
|
||||||
|
|
||||||
|
def set_solc(test_item: Test): |
||||||
|
# hacky hack hack to pick the solc version we want |
||||||
|
env = dict(os.environ) |
||||||
|
env["SOLC_VERSION"] = test_item.solc_ver |
||||||
|
os.environ.clear() |
||||||
|
os.environ.update(env) |
||||||
|
|
||||||
|
|
||||||
|
def id_test(test_item: Test): |
||||||
|
return f"{test_item.detector}: {test_item.test_file}" |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
ALL_TESTS = [ |
||||||
|
Test(UncheckedLowLevel, "tests/detectors/unchecked-lowlevel/unchecked_lowlevel.sol", "0.4.25"), |
||||||
|
Test(UncheckedLowLevel, "tests/detectors/unchecked-lowlevel/unchecked_lowlevel-0.5.1.sol", "0.5.1"), |
||||||
|
Test( |
||||||
|
UncheckedLowLevel, |
||||||
|
"tests/detectors/unchecked-lowlevel/unchecked_lowlevel-0.5.1.sol", |
||||||
|
"0.5.1", |
||||||
|
), |
||||||
|
Test( |
||||||
|
UnindexedERC20EventParameters, "tests/detectors/erc20-indexed/erc20_indexed.sol", "0.4.25" |
||||||
|
), |
||||||
|
Test( |
||||||
|
IncorrectERC20InterfaceDetection, |
||||||
|
"tests/detectors/erc20-interface/incorrect_erc20_interface.sol", |
||||||
|
"0.4.25", |
||||||
|
), |
||||||
|
Test( |
||||||
|
IncorrectERC721InterfaceDetection, |
||||||
|
"tests/detectors/erc721-interface/incorrect_erc721_interface.sol", |
||||||
|
"0.4.25", |
||||||
|
), |
||||||
|
Test( |
||||||
|
UninitializedStateVarsDetection, |
||||||
|
"tests/detectors/uninitialized-state/uninitialized.sol", |
||||||
|
"0.4.25", |
||||||
|
), |
||||||
|
Test( |
||||||
|
UninitializedStateVarsDetection, |
||||||
|
"tests/detectors/uninitialized-state/uninitialized-0.5.1.sol", |
||||||
|
"0.5.1", |
||||||
|
), |
||||||
|
Test(Backdoor, "tests/detectors/backdoor/backdoor.sol", "0.4.25"), |
||||||
|
Test(Backdoor, "tests/detectors/backdoor/backdoor.sol", "0.5.1"), |
||||||
|
Test(Suicidal, "tests/detectors/backdoor/backdoor.sol", "0.4.25"), |
||||||
|
Test(Suicidal, "tests/detectors/backdoor/backdoor.sol", "0.5.1"), |
||||||
|
Test(ConstantPragma, "tests/detectors/pragma/pragma.0.4.24.sol", "0.4.25"), |
||||||
|
Test(IncorrectSolc, "tests/detectors/solc-version/old_solc.sol", "0.4.21"), |
||||||
|
Test(IncorrectSolc, "tests/detectors/solc-version/solc_version_incorrect.sol", "0.4.25"), |
||||||
|
Test(IncorrectSolc, "tests/detectors/solc-version/solc_version_incorrect_05.sol", "0.5.7"), |
||||||
|
Test(ReentrancyEth, "tests/detectors/reentrancy-eth/reentrancy.sol", "0.4.25"), |
||||||
|
Test(ReentrancyEth, "tests/detectors/reentrancy-eth/reentrancy_indirect.sol", "0.4.25"), |
||||||
|
Test(ReentrancyEth, "tests/detectors/reentrancy-eth/reentrancy-0.5.1.sol", "0.5.1"), |
||||||
|
Test( |
||||||
|
UninitializedStorageVars, |
||||||
|
"tests/detectors/uninitialized-storage/uninitialized_storage_pointer.sol", |
||||||
|
"0.4.25", |
||||||
|
), |
||||||
|
Test(TxOrigin, "tests/detectors/tx-origin/tx_origin.sol", "0.4.25"), |
||||||
|
Test(TxOrigin, "tests/detectors/tx-origin/tx_origin-0.5.1.sol", "0.5.1"), |
||||||
|
Test(UnusedStateVars, "tests/detectors/unused-state/unused_state.sol", "0.4.25"), |
||||||
|
Test(UnusedStateVars, "tests/detectors/unused-state/unused_state.sol", "0.5.1"), |
||||||
|
Test(LockedEther, "tests/detectors/locked-ether/locked_ether.sol", "0.4.25"), |
||||||
|
Test(LockedEther, "tests/detectors/locked-ether/locked_ether-0.5.1.sol", "0.5.1"), |
||||||
|
Test(ArbitrarySend, "tests/detectors/arbitrary-send/arbitrary_send.sol", "0.4.25"), |
||||||
|
Test(ArbitrarySend, "tests/detectors/arbitrary-send/arbitrary_send-0.5.1.sol", "0.5.1"), |
||||||
|
Test(Assembly, "tests/detectors/assembly/inline_assembly_contract.sol", "0.4.25"), |
||||||
|
Test(Assembly, "tests/detectors/assembly/inline_assembly_library.sol", "0.4.25"), |
||||||
|
Test(Assembly, "tests/detectors/assembly/inline_assembly_contract-0.5.1.sol", "0.5.1"), |
||||||
|
Test(Assembly, "tests/detectors/assembly/inline_assembly_library-0.5.1.sol", "0.5.1"), |
||||||
|
Test(LowLevelCalls, "tests/detectors/low-level-calls/low_level_calls.sol", "0.4.25"), |
||||||
|
Test(LowLevelCalls, "tests/detectors/low-level-calls/low_level_calls.sol", "0.5.1"), |
||||||
|
Test( |
||||||
|
ConstCandidateStateVars, |
||||||
|
"tests/detectors/constable-states/const_state_variables.sol", |
||||||
|
"0.4.25", |
||||||
|
), |
||||||
|
Test( |
||||||
|
ConstCandidateStateVars, |
||||||
|
"tests/detectors/constable-states/const_state_variables.sol", |
||||||
|
"0.5.1", |
||||||
|
), |
||||||
|
Test(ExternalFunction, "tests/detectors/external-function/external_function.sol", "0.4.25"), |
||||||
|
Test(ExternalFunction, "tests/detectors/external-function/external_function_2.sol", "0.4.25"), |
||||||
|
Test(ExternalFunction, "tests/detectors/external-function/external_function.sol", "0.5.1"), |
||||||
|
Test(ExternalFunction, "tests/detectors/external-function/external_function_2.sol", "0.5.1"), |
||||||
|
Test(NamingConvention, "tests/detectors/naming-convention/naming_convention.sol", "0.4.25"), |
||||||
|
Test(NamingConvention, "tests/detectors/naming-convention/naming_convention.sol", "0.5.1"), |
||||||
|
Test( |
||||||
|
ControlledDelegateCall, |
||||||
|
"tests/detectors/controlled-delegatecall/controlled_delegatecall.sol", |
||||||
|
"0.4.25", |
||||||
|
), |
||||||
|
Test( |
||||||
|
ControlledDelegateCall, |
||||||
|
"tests/detectors/controlled-delegatecall/controlled_delegatecall.sol", |
||||||
|
"0.5.1", |
||||||
|
), |
||||||
|
Test( |
||||||
|
UninitializedLocalVars, |
||||||
|
"tests/detectors/uninitialized-local/uninitialized_local_variable.sol", |
||||||
|
"0.4.25", |
||||||
|
), |
||||||
|
Test(ConstantFunctionsAsm, "tests/detectors/constant/constant.sol", "0.4.25"), |
||||||
|
Test(ConstantFunctionsState, "tests/detectors/constant/constant.sol", "0.4.25"), |
||||||
|
Test(ConstantFunctionsAsm, "tests/detectors/constant/constant-0.5.1.sol", "0.5.1"), |
||||||
|
Test(ConstantFunctionsState, "tests/detectors/constant/constant-0.5.1.sol", "0.5.1"), |
||||||
|
Test(UnusedReturnValues, "tests/detectors/unused-return/unused_return.sol", "0.4.25"), |
||||||
|
Test(UnusedReturnValues, "tests/detectors/unused-return/unused_return.sol", "0.5.1"), |
||||||
|
Test( |
||||||
|
ShadowingAbstractDetection, |
||||||
|
"tests/detectors/shadowing-abstract/shadowing_abstract.sol", |
||||||
|
"0.4.25", |
||||||
|
), |
||||||
|
Test(StateShadowing, "tests/detectors/shadowing-state/shadowing_state_variable.sol", "0.4.25"), |
||||||
|
Test(Timestamp, "tests/detectors/timestamp/timestamp.sol", "0.4.25"), |
||||||
|
Test(Timestamp, "tests/detectors/timestamp/timestamp.sol", "0.5.1"), |
||||||
|
Test(MultipleCallsInLoop, "tests/detectors/calls-loop/multiple_calls_in_loop.sol", "0.4.25"), |
||||||
|
Test( |
||||||
|
BuiltinSymbolShadowing, |
||||||
|
"tests/detectors/shadowing-builtin/shadowing_builtin_symbols.sol", |
||||||
|
"0.4.25", |
||||||
|
), |
||||||
|
Test(LocalShadowing, "tests/detectors/shadowing-local/shadowing_local_variable.sol", "0.4.25"), |
||||||
|
Test(RightToLeftOverride, "tests/detectors/rtlo/right_to_left_override.sol", "0.4.25"), |
||||||
|
Test(VoidConstructor, |
||||||
|
"tests/detectors/void-cst/void-cst.sol", |
||||||
|
"0.5.1"), |
||||||
|
Test(UncheckedSend, |
||||||
|
"tests/detectors/unchecked-send/unchecked_send-0.5.1.sol", |
||||||
|
"0.5.1"), |
||||||
|
Test(ReentrancyEvent, |
||||||
|
"tests/detectors/reentrancy-events/reentrancy-0.5.1-events.sol", |
||||||
|
"0.5.1"), |
||||||
|
Test(IncorrectStrictEquality, |
||||||
|
"tests/detectors/incorrect-equality/incorrect_equality.sol", |
||||||
|
"0.5.1"), |
||||||
|
Test(TooManyDigits, |
||||||
|
"tests/detectors/too-many-digits/too_many_digits.sol", |
||||||
|
"0.5.1"), |
||||||
|
] |
||||||
|
GENERIC_PATH = "/GENERIC_PATH" |
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("test_item", ALL_TESTS, ids=id_test) |
||||||
|
def test_detector(test_item: Test): |
||||||
|
set_solc(test_item) |
||||||
|
sl = Slither(test_item.test_file) |
||||||
|
sl.register_detector(test_item.detector) |
||||||
|
results = sl.run_detectors() |
||||||
|
|
||||||
|
with open(test_item.expected_result, encoding="utf8") as f: |
||||||
|
expected_result = json.load(f) |
||||||
|
|
||||||
|
results_as_string = json.dumps(results) |
||||||
|
current_path = str(pathlib.Path(pathlib.Path().absolute(), test_item.test_file).absolute()) |
||||||
|
results_as_string = results_as_string.replace(current_path, str(pathlib.Path(GENERIC_PATH))) |
||||||
|
results = json.loads(results_as_string) |
||||||
|
|
||||||
|
diff = DeepDiff(results, expected_result, ignore_order=True, verbose_level=2) |
||||||
|
if diff: |
||||||
|
pprint(diff) |
||||||
|
diff_as_dict = diff.to_dict() |
||||||
|
|
||||||
|
if "iterable_item_added" in diff_as_dict: |
||||||
|
print("#### Findings added") |
||||||
|
for findings_added in diff_as_dict["iterable_item_added"].values(): |
||||||
|
for finding_added in findings_added: |
||||||
|
print(finding_added["description"]) |
||||||
|
if "iterable_item_removed" in diff_as_dict: |
||||||
|
print("#### Findings removed") |
||||||
|
for findings_added in diff_as_dict["iterable_item_removed"].values(): |
||||||
|
for finding_added in findings_added: |
||||||
|
print(finding_added["description"]) |
||||||
|
assert False |
||||||
|
|
||||||
|
|
||||||
|
def _generate_test(test_item: Test): |
||||||
|
set_solc(test_item) |
||||||
|
sl = Slither(test_item.test_file) |
||||||
|
sl.register_detector(test_item.detector) |
||||||
|
results = sl.run_detectors() |
||||||
|
|
||||||
|
results_as_string = json.dumps(results) |
||||||
|
current_path = str(pathlib.Path(pathlib.Path().absolute(), test_item.test_file).absolute()) |
||||||
|
results_as_string = results_as_string.replace(current_path, str(pathlib.Path(GENERIC_PATH))) |
||||||
|
results = json.loads(results_as_string) |
||||||
|
|
||||||
|
with open(test_item.expected_result, "w") as f: |
||||||
|
f.write(json.dumps(results, indent=4)) |
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__": |
||||||
|
if len(sys.argv) != 2: |
||||||
|
print('To generate the json artifacts run\n\tpython tests/test_detectors.py --generate') |
||||||
|
print('This will overwrite the previous json files') |
||||||
|
elif sys.argv[1] == "--generate": |
||||||
|
for test in ALL_TESTS: |
||||||
|
_generate_test(test) |
Loading…
Reference in new issue