Skip to content

Commit b50ce78

Browse files
authored
Merge pull request #24 from OPPIDA/feat/allsast-report-score
2 parents f95d367 + c1150c3 commit b50ce78

File tree

3 files changed

+54
-22
lines changed

3 files changed

+54
-22
lines changed

codesectools/sasts/all/cli.py

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from codesectools.sasts import SASTS_ALL
1616
from codesectools.sasts.all.sast import AllSAST
1717
from codesectools.sasts.core.sast import PrebuiltBuildlessSAST, PrebuiltSAST
18-
from codesectools.utils import group_successive
18+
from codesectools.utils import group_successive, shorten_path
1919

2020

2121
def build_cli() -> typer.Typer:
@@ -230,6 +230,7 @@ def report(
230230
) -> None:
231231
"""Generate an HTML report for a project's aggregated analysis results."""
232232
from rich.console import Console
233+
from rich.progress import track
233234
from rich.style import Style
234235
from rich.syntax import Syntax
235236
from rich.table import Table
@@ -293,15 +294,22 @@ def report(
293294
</html>
294295
"""
295296
template = template.replace(
296-
"[sasts]", ", ".join(sast.name for sast in all_sast.sasts)
297+
"[sasts]", ", ".join(sast_name for sast_name in result.sast_names)
297298
)
298299

299300
home_page = Console(record=True, file=io.StringIO())
300301

301302
main_table = Table(title="")
302-
main_table.add_column("Files (sorted by defect number)")
303+
main_table.add_column("Files")
304+
for key in list(report_data["defects"].values())[0]["score"].keys():
305+
main_table.add_column(
306+
key.replace("_", " ").title(), justify="center", no_wrap=True
307+
)
303308

304-
for defect_data in report_data["defects"].values():
309+
for defect_data in track(
310+
report_data["defects"].values(),
311+
description="Generating report for source file with defects...",
312+
):
305313
defect_report_name = (
306314
f"{sha256(defect_data['source_path'].encode()).hexdigest()}.html"
307315
)
@@ -313,13 +321,23 @@ def report(
313321
defect_stats_table.add_column(
314322
key.replace("_", " ").title(), justify="center"
315323
)
316-
defect_stats_table.add_row(*[str(v) for v in defect_data["score"].values()])
324+
325+
rendered_scores = []
326+
for v in defect_data["score"].values():
327+
if isinstance(v, float):
328+
rendered_scores.append(f"~{v}")
329+
else:
330+
rendered_scores.append(str(v))
331+
332+
defect_stats_table.add_row(*rendered_scores)
317333
defect_page.print(defect_stats_table)
318334

319335
defect_report_redirect = Text(
320-
defect_data["source_path"], style=Style(link=defect_report_name)
336+
shorten_path(defect_data["source_path"], 60),
337+
style=Style(link=defect_report_name),
321338
)
322-
main_table.add_row(defect_report_redirect)
339+
340+
main_table.add_row(defect_report_redirect, *rendered_scores)
323341

324342
# Defect table
325343
defect_table = Table(title="", show_lines=True)

codesectools/sasts/all/graphics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,7 @@ def plot_top_scores(self) -> Figure:
201201
X_files,
202202
key_values,
203203
bottom=bottoms,
204-
label=key.replace("_", " ").title(),
204+
label=f"{key.replace('_', ' ').title()} (x{2**i})",
205205
color=score_colors(i),
206206
)
207207
bottoms = [b + v for b, v in zip(bottoms, key_values, strict=False)]

codesectools/sasts/all/parser.py

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def __init__(self, name: str, analysis_results: dict[str, AnalysisResult]) -> No
1919
self.source_path = None
2020
self.analysis_results = analysis_results
2121
self.lang = None
22-
self.sasts = []
22+
self.sast_names = []
2323
self.files = set()
2424
self.defects = []
2525

@@ -30,12 +30,12 @@ def __init__(self, name: str, analysis_results: dict[str, AnalysisResult]) -> No
3030
else:
3131
assert analysis_result.lang == self.lang
3232
assert analysis_result.source_path == self.source_path
33-
self.sasts.append(sast_name)
33+
self.sast_names.append(sast_name)
3434
self.files |= set(analysis_result.files)
3535
self.defects += analysis_result.defects
3636

3737
self.category_mapping = {}
38-
for sast_name in self.sasts:
38+
for sast_name in self.sast_names:
3939
sast = SASTS_ALL[sast_name]["sast"]
4040
for category_name, color in sast.color_mapping.items():
4141
if color.lower() == "red":
@@ -55,7 +55,7 @@ def __repr__(self) -> str:
5555
return f"""{self.__class__.__name__}(
5656
name: \t{self.name}
5757
lang: \t{self.lang}
58-
sasts: \t{self.sasts}
58+
sasts: \t{self.sast_names}
5959
file_count: \t{len(self.files)}
6060
defect_count: \t{len(self.defects)}
6161
)"""
@@ -142,11 +142,15 @@ def stats_by_scores(self) -> dict:
142142
for defect_file, defects in defect_files.items():
143143
defects_cwes = {d.cwe for d in defects if d.cwe.id != -1}
144144

145-
cwes_found_by_all_sasts = 0
145+
defects_same_cwe = 0
146146
for cwe in defects_cwes:
147147
cwes_sasts = {d.sast for d in defects if d.cwe == cwe}
148-
if set(self.sasts) == cwes_sasts:
149-
cwes_found_by_all_sasts += 1
148+
if set(self.sast_names) == cwes_sasts:
149+
defects_same_cwe += 1
150+
else:
151+
defects_same_cwe += (
152+
len(set(self.sast_names) & cwes_sasts) - 1
153+
) / len(self.sast_names)
150154

151155
defect_locations = {}
152156
for defect in defects:
@@ -158,7 +162,7 @@ def stats_by_scores(self) -> dict:
158162
defects_same_location = 0
159163
defects_same_location_same_cwe = 0
160164
for _, defects_ in defect_locations.items():
161-
if set(defect.sast for defect in defects_) == set(self.sasts):
165+
if set(defect.sast for defect in defects_) == set(self.sast_names):
162166
defects_same_location += 1
163167
defects_by_cwe = {}
164168
for defect in defects_:
@@ -167,17 +171,27 @@ def stats_by_scores(self) -> dict:
167171
defects_by_cwe[defect.cwe].append(defect)
168172

169173
for _, defects_ in defects_by_cwe.items():
170-
if set(defect.sast for defect in defects_) == set(self.sasts):
174+
if set(defect.sast for defect in defects_) == set(
175+
self.sast_names
176+
):
171177
defects_same_location_same_cwe += 1
178+
else:
179+
defects_same_location_same_cwe += (
180+
len(
181+
set(defect.sast for defect in defects_)
182+
& set(self.sast_names)
183+
)
184+
- 1
185+
) / len(self.sast_names)
172186

173187
stats[defect_file] = {
174188
"score": {
175189
"defect_number": len(defects),
176-
"unique_cwes_number": len(defects_cwes),
177-
"cwes_found_by_all_sasts": cwes_found_by_all_sasts,
178-
"defects_same_location": defects_same_location,
179-
"defects_same_location_same_cwe": defects_same_location_same_cwe,
180-
}
190+
"defects_same_cwe": defects_same_cwe * 2,
191+
"defects_same_location": defects_same_location * 4,
192+
"defects_same_location_same_cwe": defects_same_location_same_cwe
193+
* 8,
194+
},
181195
}
182196

183197
return stats

0 commit comments

Comments
 (0)