Skip to content

Commit e24c63c

Browse files
authored
Merge pull request #43 from OPPIDA/fix/bug-fixes
2 parents 50df0b7 + 1f9ac60 commit e24c63c

File tree

11 files changed

+48
-32
lines changed

11 files changed

+48
-32
lines changed

codesectools/datasets/BenchmarkJava/dataset.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
from codesectools.datasets.core.dataset import File, PrebuiltFileDataset
1414
from codesectools.shared.cwe import CWE, CWEs
15+
from codesectools.utils import CPU_COUNT
1516

1617

1718
class TestCode(File):
@@ -65,7 +66,7 @@ class BenchmarkJava(PrebuiltFileDataset):
6566
license = "GPL-2.0"
6667
license_url = "https://github.com/OWASP-Benchmark/BenchmarkJava/blob/master/LICENSE"
6768

68-
build_command = "mvn clean compile"
69+
build_command = f"mvn clean compile -T {CPU_COUNT // 2}"
6970
prebuilt_expected = (Path("target/classes/org/owasp/benchmark/testcode"), "*.class")
7071
artifacts_arg = "."
7172

codesectools/sasts/all/parser.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,10 +151,11 @@ def stats_by_scores(self) -> dict:
151151
]
152152
)
153153

154-
for line in defect.lines:
155-
if not defect_locations.get(line):
156-
defect_locations[line] = []
157-
defect_locations[line].append(defect)
154+
if defect.lines:
155+
for line in defect.lines:
156+
if not defect_locations.get(line):
157+
defect_locations[line] = []
158+
defect_locations[line].append(defect)
158159

159160
same_location = 0
160161
same_location_same_cwe = 0

codesectools/sasts/all/report.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def generate_single_defect(self, defect_file: dict) -> str:
130130
else "None"
131131
)
132132
rows.append(
133-
(float("inf"), "None", defect.sast, cwe_link, defect.message)
133+
(float("inf"), "None", defect.sast_name, cwe_link, defect.message)
134134
)
135135

136136
for row in sorted(rows, key=lambda r: r[0]):
@@ -176,7 +176,12 @@ def generate_single_defect(self, defect_file: dict) -> str:
176176

177177
html_content = file_page.export_html(code_format=self.TEMPLATE)
178178
html_content = html_content.replace('href="HACK', 'id="')
179-
html_content = html_content.replace("[name]", defect_file["source_path"])
179+
html_content = html_content.replace(
180+
"[name]",
181+
str(
182+
Path(defect_file["source_path"]).relative_to(self.result.source_path) # ty:ignore[no-matching-overload]
183+
),
184+
)
180185
html_content = html_content.replace("[tippy_calls]", tippy_calls)
181186

182187
return html_content

codesectools/sasts/core/parser/__init__.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,10 @@ def __init__(
5252
lines: A list of line numbers where the defect is located.
5353
5454
"""
55+
if not filepath.is_file():
56+
raise FileNotFoundError(filepath.resolve())
5557
self.filepath = filepath
56-
self.filepath_str = str(filepath)
58+
self.filepath_str = str(filepath.resolve())
5759
self.filename = filepath.name
5860
self.sast_name = sast_name
5961
self.checker = checker
@@ -70,6 +72,7 @@ def __repr__(self) -> str:
7072
7173
"""
7274
return f"""{self.__class__.__name__}(
75+
sast: \t{self.sast_name}
7376
filepath: \t{self.filepath}
7477
checker: \t{self.checker}
7578
level: \t{self.level}

codesectools/sasts/core/parser/format/SARIF/parser.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ def __init__(
5454
for result in self.results:
5555
filepath, lines = self.get_location(result)
5656

57+
if not filepath:
58+
continue
59+
5760
if rule_id := result.rule_id:
5861
rule = self.rules[rule_id]
5962

@@ -114,15 +117,16 @@ def get_rule_properties(self, rule_id: str) -> PropertyBag | None:
114117
return properties
115118
return None
116119

117-
def get_location(self, result: Result) -> tuple[Path, list[int] | None]:
120+
def get_location(self, result: Result) -> tuple[Path | None, list[int]]:
118121
"""Extract the file path and line numbers from a SARIF result."""
119-
lines = None
122+
filepath = None
123+
lines = []
120124
if result.locations:
121125
if physical_location := result.locations[0].physical_location:
122126
if root := physical_location.root:
123127
if artifact_location := root.artifact_location:
124128
if uri := artifact_location.uri:
125-
filepath = Path(uri)
129+
filepath = self.source_path / uri
126130

127131
if region := root.region:
128132
lines = [

codesectools/sasts/tools/SpotBugs/parser.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from __future__ import annotations
99

10+
from collections import defaultdict
1011
from pathlib import Path
1112
from typing import TYPE_CHECKING, Any
1213

@@ -29,30 +30,27 @@ class SpotBugsAnalysisResult(SARIFAnalysisResult):
2930
# /home/user/mypackage/src/main/java/org/mypackage/...
3031
def patch_dict(self, sarif_dict: dict) -> dict:
3132
"""Patch the SARIF dictionary to resolve relative Java class paths."""
32-
partial_parents = {}
33+
file_index = defaultdict(list)
34+
for file_path in self.source_path.rglob("*.java"): # SpotBugs only support Java
35+
file_index[file_path.name].append(file_path)
3336

3437
def recursive_patch(data: Any) -> None: # noqa: ANN401
3538
if isinstance(data, dict):
3639
for key, value in data.items():
3740
if key == "uri":
3841
partial_filepath = Path(value)
39-
if partial_filepath.parent not in partial_parents:
40-
if next(
41-
self.source_path.rglob(str(partial_filepath)), None
42+
candidates = file_index.get(partial_filepath.name, [])
43+
44+
found = None
45+
for candidate in candidates:
46+
if (
47+
candidate.parts[-len(partial_filepath.parts) :]
48+
== partial_filepath.parts
4249
):
43-
filepath = next(
44-
self.source_path.rglob(str(partial_filepath))
45-
).relative_to(self.source_path)
46-
partial_parents[partial_filepath.parent] = (
47-
filepath.parent
48-
)
49-
else:
50-
filepath = (
51-
partial_parents[partial_filepath.parent]
52-
/ partial_filepath.name
53-
)
50+
found = str(candidate.resolve())
51+
break
5452

55-
data[key] = str(filepath)
53+
data[key] = found if found else None
5654
else:
5755
recursive_patch(value)
5856

codesectools/sasts/tools/SpotBugs/sast.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ class SpotBugsSAST(PrebuiltSAST):
6161
[
6262
"spotbugs",
6363
"-textui",
64+
"-maxHeap",
65+
"4096",
6466
"-nested:true",
6567
"-progress",
6668
"-sarif=spotbugs.sarif",

codesectools/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,4 @@ def shorten_path(path: str, max_len: int = 20) -> str:
259259
return str(shortened_path)
260260

261261

262-
CPU_COUNT = os.cpu_count()
262+
CPU_COUNT = os.cpu_count() or 2

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "CodeSecTools"
3-
version = "0.15.1"
3+
version = "0.15.2"
44
description = "A framework for code security that provides abstractions for static analysis tools and datasets to support their integration, testing, and evaluation."
55
readme = "README.md"
66
license = "AGPL-3.0-only"

tests/test_all_sasts.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from codesectools.sasts import SASTS_ALL
1212
from codesectools.sasts.all.cli import build_cli
1313
from codesectools.sasts.all.sast import AllSAST
14-
from codesectools.utils import run_command
14+
from codesectools.utils import CPU_COUNT, run_command
1515

1616
all_sast = AllSAST()
1717

@@ -46,7 +46,9 @@ def test_analyze(monkeypatch: pytest.MonkeyPatch) -> None:
4646
git.Repo.clone_from("https://github.com/appsecco/dvja.git", "/tmp/dvja")
4747
monkeypatch.chdir("/tmp/dvja")
4848

49-
retcode, stdout = run_command("mvn clean compile".split(" "), cwd=Path("/tmp/dvja"))
49+
retcode, stdout = run_command(
50+
f"mvn clean compile -T {CPU_COUNT // 2}".split(" "), cwd=Path("/tmp/dvja")
51+
)
5052
assert retcode == 0
5153

5254
result = runner.invoke(

0 commit comments

Comments
 (0)