Skip to content

Commit a16cb5b

Browse files
authored
Fixes failure to scan single cargo manifests (#4582)
* fix: prevent 'NoneType' error when scanning single Cargo.toml files Signed-off-by: Om Santosh Suneri <142336291+omsuneri@users.noreply.github.com> * fix: use cached parent resource instead of redundant parent() call Signed-off-by: Om Santosh Suneri <142336291+omsuneri@users.noreply.github.com> * Add regression test for single Cargo.toml file scan Signed-off-by: Om Santosh Suneri <142336291+omsuneri@users.noreply.github.com> * refactor: remove unnecessary portion of test file Cargo.toml Signed-off-by: Om Santosh Suneri <142336291+omsuneri@users.noreply.github.com> * refactor: test with a full --package scan Signed-off-by: Om Santosh Suneri <142336291+omsuneri@users.noreply.github.com> * refactor: removing header from the ```cargo.toml.expected``` Signed-off-by: Om Santosh Suneri <142336291+omsuneri@users.noreply.github.com> --------- Signed-off-by: Om Santosh Suneri <142336291+omsuneri@users.noreply.github.com>
1 parent 930e30e commit a16cb5b

File tree

5 files changed

+168
-8
lines changed

5 files changed

+168
-8
lines changed

src/packagedcode/cargo.py

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,13 @@ def assemble(cls, package_data, resource, codebase, package_adder):
6767
package_data.extra_data[attribute] = 'workspace'
6868
workspace_package_data[attribute] = getattr(package_data, attribute)
6969

70-
workspace_root_path = resource.parent(codebase).path
70+
workspace_root = resource.parent(codebase)
71+
if not workspace_root:
72+
# If there's no parent (e.g., scanning a single file), use the directory part of the resource path
73+
workspace_root_path = os.path.dirname(resource.path)
74+
else:
75+
workspace_root_path = workspace_root.path
76+
7177
if workspace_package_data and workspace_members:
7278

7379
# TODO: support glob patterns found in cargo workspaces
@@ -103,12 +109,14 @@ def assemble(cls, package_data, resource, codebase, package_adder):
103109
package_adder=package_adder,
104110
)
105111
else:
106-
yield from cls.assemble_from_many_datafiles(
107-
datafile_name_patterns=('Cargo.toml', 'cargo.toml', 'Cargo.lock', 'cargo.lock'),
108-
directory=resource.parent(codebase),
109-
codebase=codebase,
110-
package_adder=package_adder,
111-
)
112+
parent_resource = resource.parent(codebase)
113+
if parent_resource:
114+
yield from cls.assemble_from_many_datafiles(
115+
datafile_name_patterns=('Cargo.toml', 'cargo.toml', 'Cargo.lock', 'cargo.lock'),
116+
directory=parent_resource,
117+
codebase=codebase,
118+
package_adder=package_adder,
119+
)
112120

113121
@classmethod
114122
def update_resource_package_data(cls, workspace, workspace_package_data, resource_package_data, mapping=None):

src/packagedcode/npm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def assemble(cls, package_data, resource, codebase, package_adder):
125125
workspace_root = package_resource.parent(codebase)
126126
workspace_root_path = None
127127
if workspace_root:
128-
workspace_root_path = package_resource.parent(codebase).path
128+
workspace_root_path = workspace_root.path
129129
workspaces = pkg_data.extra_data.get('workspaces') or []
130130

131131
# Also look for pnpm workspaces
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
[package]
2+
name = "constant_time_eq"
3+
version = "0.4.2"
4+
edition = "2024"
5+
authors = ["Cesar Eduardo Barros <cesarb@cesarb.eti.br>"]
6+
description = "Compares two equal-sized byte strings in constant time."
7+
documentation = "https://docs.rs/constant_time_eq"
8+
repository = "https://github.com/cesarb/constant_time_eq"
9+
readme = "README"
10+
keywords = ["constant_time"]
11+
categories = ["cryptography", "no-std"]
12+
license = "CC0-1.0 OR MIT-0 OR Apache-2.0"
13+
rust-version = "1.85.0"
14+
15+
[dev-dependencies]
16+
criterion = { version = "0.5.1", features = ["cargo_bench_support", "html_reports"] }
17+
count_instructions = "0.2.0"
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
{
2+
"packages": [],
3+
"dependencies": [],
4+
"files": [
5+
{
6+
"path": "Cargo.toml",
7+
"type": "file",
8+
"package_data": [
9+
{
10+
"type": "cargo",
11+
"namespace": null,
12+
"name": "constant_time_eq",
13+
"version": "0.4.2",
14+
"qualifiers": {},
15+
"subpath": null,
16+
"primary_language": "Rust",
17+
"description": "Compares two equal-sized byte strings in constant time.",
18+
"release_date": null,
19+
"parties": [
20+
{
21+
"type": "person",
22+
"role": "author",
23+
"name": "Cesar Eduardo Barros",
24+
"email": "cesarb@cesarb.eti.br",
25+
"url": null
26+
}
27+
],
28+
"keywords": [
29+
"constant_time",
30+
"cryptography",
31+
"no-std"
32+
],
33+
"homepage_url": null,
34+
"download_url": null,
35+
"size": null,
36+
"sha1": null,
37+
"md5": null,
38+
"sha256": null,
39+
"sha512": null,
40+
"bug_tracking_url": null,
41+
"code_view_url": null,
42+
"vcs_url": "https://github.com/cesarb/constant_time_eq",
43+
"copyright": null,
44+
"holder": null,
45+
"declared_license_expression": "cc0-1.0 OR mit-0 OR apache-2.0",
46+
"declared_license_expression_spdx": "CC0-1.0 OR MIT-0 OR Apache-2.0",
47+
"license_detections": [
48+
{
49+
"license_expression": "cc0-1.0 OR mit-0 OR apache-2.0",
50+
"license_expression_spdx": "CC0-1.0 OR MIT-0 OR Apache-2.0",
51+
"matches": [
52+
{
53+
"license_expression": "cc0-1.0 OR mit-0 OR apache-2.0",
54+
"license_expression_spdx": "CC0-1.0 OR MIT-0 OR Apache-2.0",
55+
"from_file": "Cargo.toml",
56+
"start_line": 1,
57+
"end_line": 1,
58+
"matcher": "1-spdx-id",
59+
"score": 100.0,
60+
"matched_length": 10,
61+
"match_coverage": 100.0,
62+
"rule_relevance": 100,
63+
"rule_identifier": "spdx-license-identifier-cc0_1_0_or_mit_0_or_apache_2_0-f44a2ec174eb034bd3c662f728664281e507b20d",
64+
"rule_url": null,
65+
"matched_text": "CC0-1.0 OR MIT-0 OR Apache-2.0"
66+
}
67+
],
68+
"identifier": "cc0_1_0_or_mit_0_or_apache_2_0-3f14dd48-7cd8-cf28-d4e1-3b0174a587ee"
69+
}
70+
],
71+
"other_license_expression": null,
72+
"other_license_expression_spdx": null,
73+
"other_license_detections": [],
74+
"extracted_license_statement": "CC0-1.0 OR MIT-0 OR Apache-2.0",
75+
"notice_text": null,
76+
"source_packages": [],
77+
"file_references": [],
78+
"is_private": false,
79+
"is_virtual": false,
80+
"extra_data": {
81+
"documentation_url": "https://docs.rs/constant_time_eq",
82+
"rust_version": "1.85.0",
83+
"rust_edition": "2024"
84+
},
85+
"dependencies": [
86+
{
87+
"purl": "pkg:cargo/criterion",
88+
"extracted_requirement": "0.5.1",
89+
"scope": "dev-dependencies",
90+
"is_runtime": false,
91+
"is_optional": false,
92+
"is_pinned": false,
93+
"is_direct": true,
94+
"resolved_package": {},
95+
"extra_data": {
96+
"version": "0.5.1",
97+
"features": [
98+
"cargo_bench_support",
99+
"html_reports"
100+
]
101+
}
102+
},
103+
{
104+
"purl": "pkg:cargo/count_instructions",
105+
"extracted_requirement": "0.2.0",
106+
"scope": "dev-dependencies",
107+
"is_runtime": false,
108+
"is_optional": false,
109+
"is_pinned": false,
110+
"is_direct": true,
111+
"resolved_package": {},
112+
"extra_data": {}
113+
}
114+
],
115+
"repository_homepage_url": "https://crates.io/crates/constant_time_eq",
116+
"repository_download_url": "https://crates.io/api/v1/crates/constant_time_eq/0.4.2/download",
117+
"api_data_url": "https://crates.io/api/v1/crates/constant_time_eq",
118+
"datasource_id": "cargo_toml",
119+
"purl": "pkg:cargo/constant_time_eq@0.4.2"
120+
}
121+
],
122+
"for_packages": [],
123+
"scan_errors": []
124+
}
125+
]
126+
}

tests/packagedcode/test_cargo.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,15 @@ def test_parse_cargo_toml_workspace_with_dependencies_child(self):
8383
packages_data = cargo.CargoTomlHandler.parse(test_file)
8484
self.check_packages_data(packages_data, expected_loc, regen=REGEN_TEST_FIXTURES)
8585

86+
def test_parse_cargo_toml_single_file_no_crash(self):
87+
test_file = self.get_test_loc('cargo/cargo_toml/single-file-scan/Cargo.toml')
88+
expected_file = self.get_test_loc('cargo/cargo_toml/single-file-scan/Cargo.toml.expected')
89+
result_file = self.get_temp_file('results.json')
90+
run_scan_click(['--package', test_file, '--json', result_file])
91+
check_json_scan(
92+
expected_file, result_file, remove_uuid=True, regen=REGEN_TEST_FIXTURES
93+
)
94+
8695
def test_parse_cargo_toml_tauri_workspace_in_version(self):
8796
test_file = self.get_test_loc('cargo/cargo_toml/tauri-examples/Cargo.toml')
8897
expected_loc = self.get_test_loc('cargo/cargo_toml/tauri-examples/Cargo.toml.expected')

0 commit comments

Comments
 (0)