Skip to content

Commit 95a854f

Browse files
authored
Merge pull request #201 from sethmlarson/sbom-spdx-id-stable
Make SPDX IDs stable for non-collisions
2 parents c2d29d1 + 65c4630 commit 95a854f

File tree

4 files changed

+23
-18
lines changed

4 files changed

+23
-18
lines changed

sbom.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -100,10 +100,15 @@ class CreationInfo(TypedDict):
100100
def spdx_id(value: LiteralString) -> str:
101101
"""Encode a value into characters that are valid in an SPDX ID"""
102102
value_as_spdx_id = re.sub(r"[^a-zA-Z0-9.\-]+", "-", value)
103-
# To avoid collisions we append a hash suffix.
104-
suffix = hashlib.sha256(value.encode()).hexdigest()[:8]
105-
value_as_spdx_id = f"{value_as_spdx_id}-{suffix}"
106-
assert _SPDX_IDS_TO_VALUES.setdefault(value_as_spdx_id, value) == value
103+
104+
# The happy path is there are no collisions.
105+
# But collisions can happen, especially in file paths.
106+
# We append a hash suffix in those cases.
107+
if _SPDX_IDS_TO_VALUES.setdefault(value_as_spdx_id, value) != value:
108+
suffix = hashlib.sha256(value.encode()).hexdigest()[:8]
109+
value_as_spdx_id = f"{value_as_spdx_id}-{suffix}"
110+
assert _SPDX_IDS_TO_VALUES.setdefault(value_as_spdx_id, value) == value
111+
107112
return value_as_spdx_id
108113

109114

tests/sbom/sbom-with-pip-removed.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
"packages": [],
1414
"relationships": [
1515
{
16-
"relatedSpdxElement": "SPDXRef-FILE-Modules-expat-COPYING-497fb0c3",
16+
"relatedSpdxElement": "SPDXRef-FILE-Modules-expat-COPYING",
1717
"relationshipType": "CONTAINS",
18-
"spdxElementId": "SPDXRef-PACKAGE-expat-83b93528"
18+
"spdxElementId": "SPDXRef-PACKAGE-expat"
1919
}
2020
]
2121
}

tests/sbom/sbom-with-pip.json

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"files": [],
1313
"packages": [
1414
{
15-
"SPDXID": "SPDXRef-PACKAGE-pip-ced959c1",
15+
"SPDXID": "SPDXRef-PACKAGE-pip",
1616
"name": "pip",
1717
"versionInfo": "24.0",
1818
"licenseConcluded": "MIT",
@@ -38,19 +38,19 @@
3838
],
3939
"relationships": [
4040
{
41-
"relatedSpdxElement": "SPDXRef-FILE-Modules-expat-COPYING-497fb0c3",
41+
"relatedSpdxElement": "SPDXRef-FILE-Modules-expat-COPYING",
4242
"relationshipType": "CONTAINS",
43-
"spdxElementId": "SPDXRef-PACKAGE-expat-83b93528"
43+
"spdxElementId": "SPDXRef-PACKAGE-expat"
4444
},
4545
{
46-
"relatedSpdxElement": "SPDXRef-PACKAGE-urllib3-b7a198af",
46+
"relatedSpdxElement": "SPDXRef-PACKAGE-urllib3",
4747
"relationshipType": "DEPENDS_ON",
48-
"spdxElementId": "SPDXRef-PACKAGE-pip-ced959c1"
48+
"spdxElementId": "SPDXRef-PACKAGE-pip"
4949
},
5050
{
51-
"relatedSpdxElement": "SPDXRef-PACKAGE-pip-ced959c1",
51+
"relatedSpdxElement": "SPDXRef-PACKAGE-pip",
5252
"relationshipType": "DEPENDS_ON",
53-
"spdxElementId": "SPDXRef-PACKAGE-cpython-608f998c"
53+
"spdxElementId": "SPDXRef-PACKAGE-cpython"
5454
}
5555
]
5656
}

tests/test_sbom.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
@pytest.mark.parametrize(
1515
["value", "expected"],
1616
[
17-
("abc", "abc-ba7816bf"),
18-
("def", "def-cb8379ac"),
19-
("SPDXRef-PACKAGE-pip", "SPDXRef-PACKAGE-pip-ced959c1"),
20-
("SPDXRef-PACKAGE-cpython", "SPDXRef-PACKAGE-cpython-79ab18d2"),
21-
("SPDXRef-PACKAGE-urllib3", "SPDXRef-PACKAGE-urllib3-b8ab4751"),
17+
("abc", "abc"),
18+
("path/name", "path-name"),
19+
("SPDXRef-PACKAGE-pip", "SPDXRef-PACKAGE-pip"),
20+
("SPDXRef-PACKAGE-cpython", "SPDXRef-PACKAGE-cpython"),
21+
("SPDXRef-PACKAGE-urllib3", "SPDXRef-PACKAGE-urllib3"),
2222
],
2323
)
2424
def test_spdx_id(value: str, expected: str) -> None:

0 commit comments

Comments
 (0)