@@ -20,8 +20,13 @@ SBOM_UUID_NAMESPACE = uuid.uuid5(uuid.NAMESPACE_URL, 'https://wolfssl.com/sbom/'
2020def derived_uuid (* parts ):
2121 """Deterministic UUID from joined parts under the wolfSSL SBOM namespace.
2222 Re-runs of `make sbom` against the same source produce identical UUIDs,
23- which is required for reproducible-build-style SBOM hashing."""
24- return str (uuid .uuid5 (SBOM_UUID_NAMESPACE , '/' .join (parts )))
23+ which is required for reproducible-build-style SBOM hashing.
24+
25+ Uses NUL as a separator so no aliasing is possible between e.g.
26+ derived_uuid('a/b', 'c') and derived_uuid('a', 'b/c'); NUL cannot
27+ appear in any of the call-site inputs (package name, version, role
28+ label, dep key)."""
29+ return str (uuid .uuid5 (SBOM_UUID_NAMESPACE , '\x00 ' .join (parts )))
2530
2631
2732def build_timestamp ():
@@ -148,6 +153,11 @@ def cdx_license_block(license_expr, license_text):
148153 * `license.name` - a non-listed licence (e.g. a LicenseRef-*)
149154 * `expression` - a compound SPDX expression
150155 Picking the wrong shape causes downstream tooling to reject the SBOM."""
156+ # NOASSERTION is a reserved SPDX value, not a parseable SPDX expression;
157+ # emit it via license.name so CDX validators don't choke trying to parse
158+ # it as one.
159+ if license_expr == 'NOASSERTION' :
160+ return [{'license' : {'name' : 'NOASSERTION' }}]
151161 if is_simple_spdx_id (license_expr ):
152162 return [{'license' : {'id' : license_expr }}]
153163 refs = extract_license_refs (license_expr )
@@ -246,7 +256,11 @@ def dep_version(key):
246256
247257def parse_options_h (path ):
248258 """Parse wolfssl/options.h and return sorted deduplicated list of
249- (name, value) pairs for every #define found."""
259+ (name, value) pairs for every #define found.
260+
261+ Trailing C/C++ comments on a #define line (`#define HAVE_FOO 42 /* x */`
262+ or `// y`) are stripped; otherwise they would land verbatim in the
263+ SBOM build properties."""
250264 try :
251265 with open (path ) as f :
252266 text = f .read ()
@@ -255,8 +269,10 @@ def parse_options_h(path):
255269 return []
256270
257271 defines = {}
258- for m in re .finditer (r'^#define[ \t]+(\w+)(?:[ \t]+(.+))?$' , text , re .MULTILINE ):
259- defines [m .group (1 )] = (m .group (2 ) or '' ).strip ()
272+ for m in re .finditer (r'^#define[ \t]+(\w+)(?:[ \t]+(.*))?$' , text , re .MULTILINE ):
273+ raw = (m .group (2 ) or '' )
274+ raw = re .split (r'/\*|//' , raw , maxsplit = 1 )[0 ]
275+ defines [m .group (1 )] = raw .strip ()
260276 return sorted (defines .items ())
261277
262278
@@ -515,10 +531,15 @@ def main():
515531
516532 license_text = load_license_text (args .license_text )
517533 if extract_license_refs (license_id ) and license_text is None :
518- print ("WARNING: --license-override uses a LicenseRef-* but "
519- "--license-text was not provided; the SBOM will embed a "
520- "placeholder. Provide SBOM_LICENSE_TEXT=<path> for full "
521- "SPDX compliance." , file = sys .stderr )
534+ sys .exit (
535+ "ERROR: --license-override contains a LicenseRef-* identifier "
536+ "but --license-text was not provided.\n "
537+ " SPDX 2.3 requires the licence text to be embedded in "
538+ "hasExtractedLicensingInfos for any LicenseRef-* used in "
539+ "licenseConcluded/licenseDeclared.\n "
540+ " Re-run with --license-text PATH (or "
541+ "`make sbom SBOM_LICENSE_TEXT=PATH`)."
542+ )
522543
523544 build_props = parse_options_h (args .options_h )
524545 lib_hash = sha256_file (args .lib )
0 commit comments