Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat/disable start #1461

Merged
merged 4 commits into from
Nov 28, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
65 changes: 63 additions & 2 deletions slither/core/slither_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ def __init__(self):

self._show_ignored_findings = False

# Maps from file to detector name to the start/end ranges for that detector.
# Infinity is used to signal a detector has no end range.
self._ignore_ranges: defaultdict[str, defaultdict[str, List[(int, int)]]] = defaultdict(
lambda: defaultdict(lambda: [])
)
# Track which files for _ignore_ranges have been processed (a processed file may have no entries in _ignore_ranges).
self._processed_ignores: Set[str] = set()

self._compilation_units: List[SlitherCompilationUnit] = []

self._contracts: List[Contract] = []
Expand Down Expand Up @@ -284,9 +292,52 @@ def offset_to_definitions(self, filename_str: str, offset: int) -> Set[Source]:
###################################################################################
###################################################################################

def parse_ignore_comments(self, file: str):
# The first time we check a file, find all start/end ignore comments and memoize them.
line_number = 1
while True:
if file in self._processed_ignores:
break

line_text = self.crytic_compile.get_code_from_line(file, line_number)
if line_text is None:
break

start_regex = r"^\s*//\s*slither-disable-start\s*([a-zA-Z0-9_,-]*)"
end_regex = r"^\s*//\s*slither-disable-end\s*([a-zA-Z0-9_,-]*)"
start_match = re.findall(start_regex, line_text.decode("utf8"))
end_match = re.findall(end_regex, line_text.decode("utf8"))

if start_match:
ignored = start_match[0].split(",")
if ignored:
for check in ignored:
vals = self._ignore_ranges[file][check]
if len(vals) == 0 or vals[-1][1] != float("inf"):
# First item in the array, or the prior item is fully populated.
self._ignore_ranges[file][check].append((line_number, float("inf")))
else:
raise Exception(
"consecutive slither-disable-starts without slither-disable-end"
)

if end_match:
ignored = end_match[0].split(",")
if ignored:
for check in ignored:
vals = self._ignore_ranges[file][check]
if len(vals) == 0 or vals[-1][1] != float("inf"):
raise Exception("slither-disable-end without slither-disable-start")
self._ignore_ranges[file][check][-1] = (vals[-1][0], line_number)

line_number += 1

self._processed_ignores.add(file)

def has_ignore_comment(self, r: Dict) -> bool:
"""
Check if the result has an ignore comment on the proceeding line, in which case, it is not valid
Check if the result has an ignore comment in the file or on the preceding line, in which
case, it is not valid
"""
if not self.crytic_compile:
return False
Expand All @@ -303,6 +354,16 @@ def has_ignore_comment(self, r: Dict) -> bool:
)

for file, lines in mapping_elements_with_lines:
self.parse_ignore_comments(file)

# Check if result is within an ignored range.
ignore_ranges = self._ignore_ranges[file][r["check"]] + self._ignore_ranges[file]["all"]
for start, end in ignore_ranges:
# The full check must be within the ignore range to be ignored.
if start < lines[0] and end > lines[-1]:
return True

# Check for next-line matchers.
ignore_line_index = min(lines) - 1
ignore_line_text = self.crytic_compile.get_code_from_line(file, ignore_line_index)
if ignore_line_text:
Expand All @@ -324,7 +385,7 @@ def valid_result(self, r: Dict) -> bool:
- All its source paths belong to the source path filtered
- Or a similar result was reported and saved during a previous run
- The --exclude-dependencies flag is set and results are only related to dependencies
- There is an ignore comment on the preceding line
- There is an ignore comment on the preceding line or in the file
"""

# Remove duplicate due to the multiple compilation support
Expand Down