slither.slither
1import logging 2from typing import Union, List, Type, Dict, Optional 3 4from crytic_compile import CryticCompile, InvalidCompilation 5 6# pylint: disable= no-name-in-module 7from slither.core.compilation_unit import SlitherCompilationUnit 8from slither.core.slither_core import SlitherCore 9from slither.detectors.abstract_detector import AbstractDetector, DetectorClassification 10from slither.exceptions import SlitherError 11from slither.printers.abstract_printer import AbstractPrinter 12from slither.solc_parsing.slither_compilation_unit_solc import SlitherCompilationUnitSolc 13from slither.vyper_parsing.vyper_compilation_unit import VyperCompilationUnit 14from slither.utils.output import Output 15from slither.vyper_parsing.ast.ast import parse 16 17logger = logging.getLogger("Slither") 18logging.basicConfig() 19 20logger_detector = logging.getLogger("Detectors") 21logger_printer = logging.getLogger("Printers") 22 23 24def _check_common_things( 25 thing_name: str, cls: Type, base_cls: Type, instances_list: List[Type[AbstractDetector]] 26) -> None: 27 28 if not issubclass(cls, base_cls) or cls is base_cls: 29 raise SlitherError( 30 f"You can't register {cls!r} as a {thing_name}. You need to pass a class that inherits from {base_cls.__name__}" 31 ) 32 33 if any(type(obj) == cls for obj in instances_list): # pylint: disable=unidiomatic-typecheck 34 raise SlitherError(f"You can't register {cls!r} twice.") 35 36 37def _update_file_scopes( 38 sol_parser: SlitherCompilationUnitSolc, 39): # pylint: disable=too-many-branches 40 """ 41 Since all definitions in a file are exported by default, including definitions from its (transitive) dependencies, 42 we can identify all top level items that could possibly be referenced within the file from its exportedSymbols. 43 It is not as straightforward for user defined types and functions as well as aliasing. See add_accessible_scopes for more details. 44 """ 45 candidates = sol_parser.compilation_unit.scopes.values() 46 learned_something = False 47 # Because solc's import allows cycle in the import graph, iterate until we aren't adding new information to the scope. 48 while True: 49 for candidate in candidates: 50 learned_something |= candidate.add_accessible_scopes() 51 if not learned_something: 52 break 53 learned_something = False 54 55 for scope in candidates: 56 for refId in scope.exported_symbols: 57 if refId in sol_parser.contracts_by_id: 58 contract = sol_parser.contracts_by_id[refId] 59 scope.contracts[contract.name] = contract 60 elif refId in sol_parser.functions_by_id: 61 functions = sol_parser.functions_by_id[refId] 62 assert len(functions) == 1 63 scope.functions.add(functions[0]) 64 elif refId in sol_parser.imports_by_id: 65 import_directive = sol_parser.imports_by_id[refId] 66 scope.imports.add(import_directive) 67 elif refId in sol_parser.top_level_variables_by_id: 68 top_level_variable = sol_parser.top_level_variables_by_id[refId] 69 scope.variables[top_level_variable.name] = top_level_variable 70 elif refId in sol_parser.top_level_events_by_id: 71 top_level_event = sol_parser.top_level_events_by_id[refId] 72 scope.events.add(top_level_event) 73 elif refId in sol_parser.top_level_structures_by_id: 74 top_level_struct = sol_parser.top_level_structures_by_id[refId] 75 scope.structures[top_level_struct.name] = top_level_struct 76 elif refId in sol_parser.top_level_type_aliases_by_id: 77 top_level_type_alias = sol_parser.top_level_type_aliases_by_id[refId] 78 scope.type_aliases[top_level_type_alias.name] = top_level_type_alias 79 elif refId in sol_parser.top_level_enums_by_id: 80 top_level_enum = sol_parser.top_level_enums_by_id[refId] 81 scope.enums[top_level_enum.name] = top_level_enum 82 elif refId in sol_parser.top_level_errors_by_id: 83 top_level_custom_error = sol_parser.top_level_errors_by_id[refId] 84 scope.custom_errors.add(top_level_custom_error) 85 else: 86 logger.error( 87 f"Failed to resolved name for reference id {refId} in {scope.filename.absolute}." 88 ) 89 90 91class Slither( 92 SlitherCore 93): # pylint: disable=too-many-instance-attributes,too-many-locals,too-many-statements,too-many-branches 94 def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None: 95 """ 96 Args: 97 target (str | CryticCompile) 98 Keyword Args: 99 solc (str): solc binary location (default 'solc') 100 disable_solc_warnings (bool): True to disable solc warnings (default false) 101 solc_args (str): solc arguments (default '') 102 ast_format (str): ast format (default '--ast-compact-json') 103 filter_paths (list(str)): list of path to filter (default []) 104 triage_mode (bool): if true, switch to triage mode (default false) 105 exclude_dependencies (bool): if true, exclude results that are only related to dependencies 106 generate_patches (bool): if true, patches are generated (json output only) 107 change_line_prefix (str): Change the line prefix (default #) 108 for the displayed source codes (i.e. file.sol#1). 109 110 """ 111 super().__init__() 112 113 self._disallow_partial: bool = kwargs.get("disallow_partial", False) 114 self._skip_assembly: bool = kwargs.get("skip_assembly", False) 115 self._show_ignored_findings: bool = kwargs.get("show_ignored_findings", False) 116 117 self.line_prefix = kwargs.get("change_line_prefix", "#") 118 119 # Indicate if Codex related features should be used 120 self.codex_enabled = kwargs.get("codex", False) 121 self.codex_contracts = kwargs.get("codex_contracts", "all") 122 self.codex_model = kwargs.get("codex_model", "text-davinci-003") 123 self.codex_temperature = kwargs.get("codex_temperature", 0) 124 self.codex_max_tokens = kwargs.get("codex_max_tokens", 300) 125 self.codex_log = kwargs.get("codex_log", False) 126 self.codex_organization: Optional[str] = kwargs.get("codex_organization", None) 127 128 self.no_fail = kwargs.get("no_fail", False) 129 130 self._parsers: List[SlitherCompilationUnitSolc] = [] 131 try: 132 if isinstance(target, CryticCompile): 133 crytic_compile = target 134 else: 135 crytic_compile = CryticCompile(target, **kwargs) 136 self._crytic_compile = crytic_compile 137 except InvalidCompilation as e: 138 # pylint: disable=raise-missing-from 139 raise SlitherError(f"Invalid compilation: \n{str(e)}") 140 for compilation_unit in crytic_compile.compilation_units.values(): 141 compilation_unit_slither = SlitherCompilationUnit(self, compilation_unit) 142 self._compilation_units.append(compilation_unit_slither) 143 144 if compilation_unit_slither.is_vyper: 145 vyper_parser = VyperCompilationUnit(compilation_unit_slither) 146 for path, ast in compilation_unit.asts.items(): 147 ast_nodes = parse(ast["ast"]) 148 vyper_parser.parse_module(ast_nodes, path) 149 self._parsers.append(vyper_parser) 150 else: 151 # Solidity specific 152 assert compilation_unit_slither.is_solidity 153 sol_parser = SlitherCompilationUnitSolc(compilation_unit_slither) 154 self._parsers.append(sol_parser) 155 for path, ast in compilation_unit.asts.items(): 156 sol_parser.parse_top_level_items(ast, path) 157 self.add_source_code(path) 158 159 for contract in sol_parser._underlying_contract_to_parser: 160 if contract.name.startswith("SlitherInternalTopLevelContract"): 161 raise SlitherError( 162 # region multi-line-string 163 """Your codebase has a contract named 'SlitherInternalTopLevelContract'. 164 Please rename it, this name is reserved for Slither's internals""" 165 # endregion multi-line 166 ) 167 sol_parser._contracts_by_id[contract.id] = contract 168 sol_parser._compilation_unit.contracts.append(contract) 169 170 _update_file_scopes(sol_parser) 171 172 if kwargs.get("generate_patches", False): 173 self.generate_patches = True 174 175 self._markdown_root = kwargs.get("markdown_root", "") 176 177 self._detectors = [] 178 self._printers = [] 179 180 filter_paths = kwargs.get("filter_paths", []) 181 for p in filter_paths: 182 self.add_path_to_filter(p) 183 184 include_paths = kwargs.get("include_paths", []) 185 for p in include_paths: 186 self.add_path_to_include(p) 187 188 self._exclude_dependencies = kwargs.get("exclude_dependencies", False) 189 190 triage_mode = kwargs.get("triage_mode", False) 191 triage_database = kwargs.get("triage_database", "slither.db.json") 192 self._triage_mode = triage_mode 193 self._previous_results_filename = triage_database 194 195 printers_to_run = kwargs.get("printers_to_run", "") 196 if printers_to_run == "echidna": 197 self.skip_data_dependency = True 198 199 self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) 200 201 def _init_parsing_and_analyses(self, skip_analyze: bool) -> None: 202 203 for parser in self._parsers: 204 try: 205 parser.parse_contracts() 206 except Exception as e: 207 if self.no_fail: 208 continue 209 raise e 210 211 # skip_analyze is only used for testing 212 if not skip_analyze: 213 for parser in self._parsers: 214 try: 215 parser.analyze_contracts() 216 except Exception as e: 217 if self.no_fail: 218 continue 219 raise e 220 221 @property 222 def detectors(self): 223 return self._detectors 224 225 @property 226 def detectors_high(self): 227 return [d for d in self.detectors if d.IMPACT == DetectorClassification.HIGH] 228 229 @property 230 def detectors_medium(self): 231 return [d for d in self.detectors if d.IMPACT == DetectorClassification.MEDIUM] 232 233 @property 234 def detectors_low(self): 235 return [d for d in self.detectors if d.IMPACT == DetectorClassification.LOW] 236 237 @property 238 def detectors_informational(self): 239 return [d for d in self.detectors if d.IMPACT == DetectorClassification.INFORMATIONAL] 240 241 @property 242 def detectors_optimization(self): 243 return [d for d in self.detectors if d.IMPACT == DetectorClassification.OPTIMIZATION] 244 245 def register_detector(self, detector_class: Type[AbstractDetector]) -> None: 246 """ 247 :param detector_class: Class inheriting from `AbstractDetector`. 248 """ 249 _check_common_things("detector", detector_class, AbstractDetector, self._detectors) 250 251 for compilation_unit in self.compilation_units: 252 instance = detector_class(compilation_unit, self, logger_detector) 253 self._detectors.append(instance) 254 255 def unregister_detector(self, detector_class: Type[AbstractDetector]) -> None: 256 """ 257 :param detector_class: Class inheriting from `AbstractDetector`. 258 """ 259 260 for obj in self._detectors: 261 if isinstance(obj, detector_class): 262 self._detectors.remove(obj) 263 return 264 265 def register_printer(self, printer_class: Type[AbstractPrinter]) -> None: 266 """ 267 :param printer_class: Class inheriting from `AbstractPrinter`. 268 """ 269 _check_common_things("printer", printer_class, AbstractPrinter, self._printers) 270 271 instance = printer_class(self, logger_printer) 272 self._printers.append(instance) 273 274 def unregister_printer(self, printer_class: Type[AbstractPrinter]) -> None: 275 """ 276 :param printer_class: Class inheriting from `AbstractPrinter`. 277 """ 278 279 for obj in self._printers: 280 if isinstance(obj, printer_class): 281 self._printers.remove(obj) 282 return 283 284 def run_detectors(self) -> List[Dict]: 285 """ 286 :return: List of registered detectors results. 287 """ 288 289 self.load_previous_results() 290 results = [d.detect() for d in self._detectors] 291 292 self.write_results_to_hide() 293 return results 294 295 def run_printers(self) -> List[Output]: 296 """ 297 :return: List of registered printers outputs. 298 """ 299 300 return [p.output(self._crytic_compile.target).data for p in self._printers] 301 302 @property 303 def triage_mode(self) -> bool: 304 return self._triage_mode
92class Slither( 93 SlitherCore 94): # pylint: disable=too-many-instance-attributes,too-many-locals,too-many-statements,too-many-branches 95 def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None: 96 """ 97 Args: 98 target (str | CryticCompile) 99 Keyword Args: 100 solc (str): solc binary location (default 'solc') 101 disable_solc_warnings (bool): True to disable solc warnings (default false) 102 solc_args (str): solc arguments (default '') 103 ast_format (str): ast format (default '--ast-compact-json') 104 filter_paths (list(str)): list of path to filter (default []) 105 triage_mode (bool): if true, switch to triage mode (default false) 106 exclude_dependencies (bool): if true, exclude results that are only related to dependencies 107 generate_patches (bool): if true, patches are generated (json output only) 108 change_line_prefix (str): Change the line prefix (default #) 109 for the displayed source codes (i.e. file.sol#1). 110 111 """ 112 super().__init__() 113 114 self._disallow_partial: bool = kwargs.get("disallow_partial", False) 115 self._skip_assembly: bool = kwargs.get("skip_assembly", False) 116 self._show_ignored_findings: bool = kwargs.get("show_ignored_findings", False) 117 118 self.line_prefix = kwargs.get("change_line_prefix", "#") 119 120 # Indicate if Codex related features should be used 121 self.codex_enabled = kwargs.get("codex", False) 122 self.codex_contracts = kwargs.get("codex_contracts", "all") 123 self.codex_model = kwargs.get("codex_model", "text-davinci-003") 124 self.codex_temperature = kwargs.get("codex_temperature", 0) 125 self.codex_max_tokens = kwargs.get("codex_max_tokens", 300) 126 self.codex_log = kwargs.get("codex_log", False) 127 self.codex_organization: Optional[str] = kwargs.get("codex_organization", None) 128 129 self.no_fail = kwargs.get("no_fail", False) 130 131 self._parsers: List[SlitherCompilationUnitSolc] = [] 132 try: 133 if isinstance(target, CryticCompile): 134 crytic_compile = target 135 else: 136 crytic_compile = CryticCompile(target, **kwargs) 137 self._crytic_compile = crytic_compile 138 except InvalidCompilation as e: 139 # pylint: disable=raise-missing-from 140 raise SlitherError(f"Invalid compilation: \n{str(e)}") 141 for compilation_unit in crytic_compile.compilation_units.values(): 142 compilation_unit_slither = SlitherCompilationUnit(self, compilation_unit) 143 self._compilation_units.append(compilation_unit_slither) 144 145 if compilation_unit_slither.is_vyper: 146 vyper_parser = VyperCompilationUnit(compilation_unit_slither) 147 for path, ast in compilation_unit.asts.items(): 148 ast_nodes = parse(ast["ast"]) 149 vyper_parser.parse_module(ast_nodes, path) 150 self._parsers.append(vyper_parser) 151 else: 152 # Solidity specific 153 assert compilation_unit_slither.is_solidity 154 sol_parser = SlitherCompilationUnitSolc(compilation_unit_slither) 155 self._parsers.append(sol_parser) 156 for path, ast in compilation_unit.asts.items(): 157 sol_parser.parse_top_level_items(ast, path) 158 self.add_source_code(path) 159 160 for contract in sol_parser._underlying_contract_to_parser: 161 if contract.name.startswith("SlitherInternalTopLevelContract"): 162 raise SlitherError( 163 # region multi-line-string 164 """Your codebase has a contract named 'SlitherInternalTopLevelContract'. 165 Please rename it, this name is reserved for Slither's internals""" 166 # endregion multi-line 167 ) 168 sol_parser._contracts_by_id[contract.id] = contract 169 sol_parser._compilation_unit.contracts.append(contract) 170 171 _update_file_scopes(sol_parser) 172 173 if kwargs.get("generate_patches", False): 174 self.generate_patches = True 175 176 self._markdown_root = kwargs.get("markdown_root", "") 177 178 self._detectors = [] 179 self._printers = [] 180 181 filter_paths = kwargs.get("filter_paths", []) 182 for p in filter_paths: 183 self.add_path_to_filter(p) 184 185 include_paths = kwargs.get("include_paths", []) 186 for p in include_paths: 187 self.add_path_to_include(p) 188 189 self._exclude_dependencies = kwargs.get("exclude_dependencies", False) 190 191 triage_mode = kwargs.get("triage_mode", False) 192 triage_database = kwargs.get("triage_database", "slither.db.json") 193 self._triage_mode = triage_mode 194 self._previous_results_filename = triage_database 195 196 printers_to_run = kwargs.get("printers_to_run", "") 197 if printers_to_run == "echidna": 198 self.skip_data_dependency = True 199 200 self._init_parsing_and_analyses(kwargs.get("skip_analyze", False)) 201 202 def _init_parsing_and_analyses(self, skip_analyze: bool) -> None: 203 204 for parser in self._parsers: 205 try: 206 parser.parse_contracts() 207 except Exception as e: 208 if self.no_fail: 209 continue 210 raise e 211 212 # skip_analyze is only used for testing 213 if not skip_analyze: 214 for parser in self._parsers: 215 try: 216 parser.analyze_contracts() 217 except Exception as e: 218 if self.no_fail: 219 continue 220 raise e 221 222 @property 223 def detectors(self): 224 return self._detectors 225 226 @property 227 def detectors_high(self): 228 return [d for d in self.detectors if d.IMPACT == DetectorClassification.HIGH] 229 230 @property 231 def detectors_medium(self): 232 return [d for d in self.detectors if d.IMPACT == DetectorClassification.MEDIUM] 233 234 @property 235 def detectors_low(self): 236 return [d for d in self.detectors if d.IMPACT == DetectorClassification.LOW] 237 238 @property 239 def detectors_informational(self): 240 return [d for d in self.detectors if d.IMPACT == DetectorClassification.INFORMATIONAL] 241 242 @property 243 def detectors_optimization(self): 244 return [d for d in self.detectors if d.IMPACT == DetectorClassification.OPTIMIZATION] 245 246 def register_detector(self, detector_class: Type[AbstractDetector]) -> None: 247 """ 248 :param detector_class: Class inheriting from `AbstractDetector`. 249 """ 250 _check_common_things("detector", detector_class, AbstractDetector, self._detectors) 251 252 for compilation_unit in self.compilation_units: 253 instance = detector_class(compilation_unit, self, logger_detector) 254 self._detectors.append(instance) 255 256 def unregister_detector(self, detector_class: Type[AbstractDetector]) -> None: 257 """ 258 :param detector_class: Class inheriting from `AbstractDetector`. 259 """ 260 261 for obj in self._detectors: 262 if isinstance(obj, detector_class): 263 self._detectors.remove(obj) 264 return 265 266 def register_printer(self, printer_class: Type[AbstractPrinter]) -> None: 267 """ 268 :param printer_class: Class inheriting from `AbstractPrinter`. 269 """ 270 _check_common_things("printer", printer_class, AbstractPrinter, self._printers) 271 272 instance = printer_class(self, logger_printer) 273 self._printers.append(instance) 274 275 def unregister_printer(self, printer_class: Type[AbstractPrinter]) -> None: 276 """ 277 :param printer_class: Class inheriting from `AbstractPrinter`. 278 """ 279 280 for obj in self._printers: 281 if isinstance(obj, printer_class): 282 self._printers.remove(obj) 283 return 284 285 def run_detectors(self) -> List[Dict]: 286 """ 287 :return: List of registered detectors results. 288 """ 289 290 self.load_previous_results() 291 results = [d.detect() for d in self._detectors] 292 293 self.write_results_to_hide() 294 return results 295 296 def run_printers(self) -> List[Output]: 297 """ 298 :return: List of registered printers outputs. 299 """ 300 301 return [p.output(self._crytic_compile.target).data for p in self._printers] 302 303 @property 304 def triage_mode(self) -> bool: 305 return self._triage_mode
Slither static analyzer
95 def __init__(self, target: Union[str, CryticCompile], **kwargs) -> None: 96 """ 97 Args: 98 target (str | CryticCompile) 99 Keyword Args: 100 solc (str): solc binary location (default 'solc') 101 disable_solc_warnings (bool): True to disable solc warnings (default false) 102 solc_args (str): solc arguments (default '') 103 ast_format (str): ast format (default '--ast-compact-json') 104 filter_paths (list(str)): list of path to filter (default []) 105 triage_mode (bool): if true, switch to triage mode (default false) 106 exclude_dependencies (bool): if true, exclude results that are only related to dependencies 107 generate_patches (bool): if true, patches are generated (json output only) 108 change_line_prefix (str): Change the line prefix (default #) 109 for the displayed source codes (i.e. file.sol#1). 110 111 """ 112 super().__init__() 113 114 self._disallow_partial: bool = kwargs.get("disallow_partial", False) 115 self._skip_assembly: bool = kwargs.get("skip_assembly", False) 116 self._show_ignored_findings: bool = kwargs.get("show_ignored_findings", False) 117 118 self.line_prefix = kwargs.get("change_line_prefix", "#") 119 120 # Indicate if Codex related features should be used 121 self.codex_enabled = kwargs.get("codex", False) 122 self.codex_contracts = kwargs.get("codex_contracts", "all") 123 self.codex_model = kwargs.get("codex_model", "text-davinci-003") 124 self.codex_temperature = kwargs.get("codex_temperature", 0) 125 self.codex_max_tokens = kwargs.get("codex_max_tokens", 300) 126 self.codex_log = kwargs.get("codex_log", False) 127 self.codex_organization: Optional[str] = kwargs.get("codex_organization", None) 128 129 self.no_fail = kwargs.get("no_fail", False) 130 131 self._parsers: List[SlitherCompilationUnitSolc] = [] 132 try: 133 if isinstance(target, CryticCompile): 134 crytic_compile = target 135 else: 136 crytic_compile = CryticCompile(target, **kwargs) 137 self._crytic_compile = crytic_compile 138 except InvalidCompilation as e: 139 # pylint: disable=raise-missing-from 140 raise SlitherError(f"Invalid compilation: \n{str(e)}") 141 for compilation_unit in crytic_compile.compilation_units.values(): 142 compilation_unit_slither = SlitherCompilationUnit(self, compilation_unit) 143 self._compilation_units.append(compilation_unit_slither) 144 145 if compilation_unit_slither.is_vyper: 146 vyper_parser = VyperCompilationUnit(compilation_unit_slither) 147 for path, ast in compilation_unit.asts.items(): 148 ast_nodes = parse(ast["ast"]) 149 vyper_parser.parse_module(ast_nodes, path) 150 self._parsers.append(vyper_parser) 151 else: 152 # Solidity specific 153 assert compilation_unit_slither.is_solidity 154 sol_parser = SlitherCompilationUnitSolc(compilation_unit_slither) 155 self._parsers.append(sol_parser) 156 for path, ast in compilation_unit.asts.items(): 157 sol_parser.parse_top_level_items(ast, path) 158 self.add_source_code(path) 159 160 for contract in sol_parser._underlying_contract_to_parser: 161 if contract.name.startswith("SlitherInternalTopLevelContract"): 162 raise SlitherError( 163 # region multi-line-string 164 """Your codebase has a contract named 'SlitherInternalTopLevelContract'. 165 Please rename it, this name is reserved for Slither's internals""" 166 # endregion multi-line 167 ) 168 sol_parser._contracts_by_id[contract.id] = contract 169 sol_parser._compilation_unit.contracts.append(contract) 170 171 _update_file_scopes(sol_parser) 172 173 if kwargs.get("generate_patches", False): 174 self.generate_patches = True 175 176 self._markdown_root = kwargs.get("markdown_root", "") 177 178 self._detectors = [] 179 self._printers = [] 180 181 filter_paths = kwargs.get("filter_paths", []) 182 for p in filter_paths: 183 self.add_path_to_filter(p) 184 185 include_paths = kwargs.get("include_paths", []) 186 for p in include_paths: 187 self.add_path_to_include(p) 188 189 self._exclude_dependencies = kwargs.get("exclude_dependencies", False) 190 191 triage_mode = kwargs.get("triage_mode", False) 192 triage_database = kwargs.get("triage_database", "slither.db.json") 193 self._triage_mode = triage_mode 194 self._previous_results_filename = triage_database 195 196 printers_to_run = kwargs.get("printers_to_run", "") 197 if printers_to_run == "echidna": 198 self.skip_data_dependency = True 199 200 self._init_parsing_and_analyses(kwargs.get("skip_analyze", False))
Args: target (str | CryticCompile) Keyword Args: solc (str): solc binary location (default 'solc') disable_solc_warnings (bool): True to disable solc warnings (default false) solc_args (str): solc arguments (default '') ast_format (str): ast format (default '--ast-compact-json') filter_paths (list(str)): list of path to filter (default []) triage_mode (bool): if true, switch to triage mode (default false) exclude_dependencies (bool): if true, exclude results that are only related to dependencies generate_patches (bool): if true, patches are generated (json output only) change_line_prefix (str): Change the line prefix (default #) for the displayed source codes (i.e. file.sol#1).
246 def register_detector(self, detector_class: Type[AbstractDetector]) -> None: 247 """ 248 :param detector_class: Class inheriting from `AbstractDetector`. 249 """ 250 _check_common_things("detector", detector_class, AbstractDetector, self._detectors) 251 252 for compilation_unit in self.compilation_units: 253 instance = detector_class(compilation_unit, self, logger_detector) 254 self._detectors.append(instance)
Parameters
- detector_class: Class inheriting from
AbstractDetector
.
256 def unregister_detector(self, detector_class: Type[AbstractDetector]) -> None: 257 """ 258 :param detector_class: Class inheriting from `AbstractDetector`. 259 """ 260 261 for obj in self._detectors: 262 if isinstance(obj, detector_class): 263 self._detectors.remove(obj) 264 return
Parameters
- detector_class: Class inheriting from
AbstractDetector
.
266 def register_printer(self, printer_class: Type[AbstractPrinter]) -> None: 267 """ 268 :param printer_class: Class inheriting from `AbstractPrinter`. 269 """ 270 _check_common_things("printer", printer_class, AbstractPrinter, self._printers) 271 272 instance = printer_class(self, logger_printer) 273 self._printers.append(instance)
Parameters
- printer_class: Class inheriting from
AbstractPrinter
.
275 def unregister_printer(self, printer_class: Type[AbstractPrinter]) -> None: 276 """ 277 :param printer_class: Class inheriting from `AbstractPrinter`. 278 """ 279 280 for obj in self._printers: 281 if isinstance(obj, printer_class): 282 self._printers.remove(obj) 283 return
Parameters
- printer_class: Class inheriting from
AbstractPrinter
.
285 def run_detectors(self) -> List[Dict]: 286 """ 287 :return: List of registered detectors results. 288 """ 289 290 self.load_previous_results() 291 results = [d.detect() for d in self._detectors] 292 293 self.write_results_to_hide() 294 return results
Returns
List of registered detectors results.
296 def run_printers(self) -> List[Output]: 297 """ 298 :return: List of registered printers outputs. 299 """ 300 301 return [p.output(self._crytic_compile.target).data for p in self._printers]
Returns
List of registered printers outputs.
Inherited Members
- slither.core.slither_core.SlitherCore
- sarif_input
- sarif_triage
- skip_data_dependency
- compilation_units
- add_compilation_unit
- contracts
- contracts_derived
- get_contract_from_name
- source_code
- filename
- add_source_code
- markdown_root
- print_functions
- offset_to_objects
- offset_to_references
- offset_to_implementations
- offset_to_definitions
- parse_ignore_comments
- has_ignore_comment
- valid_result
- load_previous_results
- load_previous_results_from_sarif
- write_results_to_hide
- save_results_to_hide
- add_path_to_filter
- add_path_to_include
- crytic_compile
- generate_patches
- disallow_partial
- skip_assembly
- show_ignore_findings