Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion share/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ into a product at `tools/sbom/`, together with the pin files (`VERSION` and
Every front end produces a composition input and a config input and hands them to
the driver.

Composition (at least one):
Composition (pick one):

- `--srcs-file PATH` — the source files compiled into the artifact (tier E).
- `--lib PATH` — the built library to hash (tier R/L/S).
Expand Down
16 changes: 13 additions & 3 deletions share/build/sbom.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
# LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/LICENSE
# )
#
# Composition, one of: TARGETS <tgt>... (hash the source set), LIB <path>
# (hash the built library), or NO_ARTIFACT_HASH alone.
#
# Optional arguments:
# SBOM_GEN <path> Path to gen-sbom (default: driver auto-discovery).
# GEN_SBOM <path> Legacy alias for SBOM_GEN.
Expand Down Expand Up @@ -117,13 +120,20 @@ function(wolfssl_compliance_tooling_add_sbom)
if(NOT SB_NAME)
message(FATAL_ERROR "wolfssl_compliance_tooling_add_sbom: NAME is required")
endif()
if(SB_LIB MATCHES "-NOTFOUND$")
message(FATAL_ERROR
"wolfssl_compliance_tooling_add_sbom: LIB was not found (${SB_LIB})")
endif()
if(SB_NO_ARTIFACT_HASH)
if(SB_TARGETS OR SB_LIB)
if(SB_TARGETS OR NOT "${SB_LIB}" STREQUAL "")
message(FATAL_ERROR
"wolfssl_compliance_tooling_add_sbom: NO_ARTIFACT_HASH stands "
"alone. Do not pass TARGETS or LIB.")
endif()
elseif(NOT SB_TARGETS AND NOT SB_LIB)
elseif(SB_TARGETS AND NOT "${SB_LIB}" STREQUAL "")
message(FATAL_ERROR
"wolfssl_compliance_tooling_add_sbom: set TARGETS or LIB, not both")
elseif(NOT SB_TARGETS AND "${SB_LIB}" STREQUAL "")
message(FATAL_ERROR "wolfssl_compliance_tooling_add_sbom: set TARGETS or LIB")
endif()
if(NOT SB_ROOT)
Expand Down Expand Up @@ -190,7 +200,7 @@ function(wolfssl_compliance_tooling_add_sbom)
file(GENERATE OUTPUT ${_srcs_file} CONTENT "${_srcs_nl}\n")
list(APPEND _cmd --srcs-file ${_srcs_file})
endif()
if(SB_LIB)
if(NOT "${SB_LIB}" STREQUAL "")
list(APPEND _cmd --lib ${SB_LIB})
endif()
endif()
Expand Down
1 change: 1 addition & 0 deletions share/build/sbom.mk
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ $(1): $($(2)PREREQS)
else \
test -n "$(strip $($(2)SRCS))$($(2)LIB)" || \
{ echo "ERROR: set $(2)SRCS or $(2)LIB"; exit 1; }; \
$(if $(and $(strip $($(2)SRCS)),$($(2)LIB)),{ echo "ERROR: set $(2)SRCS or $(2)LIB but not both"; exit 1; };) \
fi
@set -e; \
if [ -n "$(strip $($(2)SRCS))" ]; then \
Expand Down
3 changes: 1 addition & 2 deletions share/gen-sbom
Original file line number Diff line number Diff line change
Expand Up @@ -895,8 +895,7 @@ def parse_options_h(path):
with open(path) as f:
text = f.read()
except OSError as e:
print(f"WARNING: cannot read options.h {path}: {e}", file=sys.stderr)
return []
sys.exit(f"ERROR: cannot read --options-h {path}: {e}")

defines = {}
for m in re.finditer(r'^#define[ \t]+(\w+)(?:[ \t]+(.*))?$', text, re.MULTILINE):
Expand Down
6 changes: 4 additions & 2 deletions share/sbom-driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,8 @@ def main():
description=__doc__,
formatter_class=argparse.RawDescriptionHelpFormatter)

# Composition (at least one of --lib / --srcs-file; --source-only needs srcs).
# Composition (one of --lib / --srcs-file / --no-artifact-hash;
# --source-only needs srcs).
ap.add_argument("--lib", default="",
help="Path to the built library to hash (tier R/L/S).")
ap.add_argument("--srcs-file", default="",
Expand Down Expand Up @@ -367,7 +368,8 @@ def main():
elif args.lib and args.srcs_file:
sys.exit("ERROR: pass one of --lib or --srcs-file.")
elif not args.lib and not args.srcs_file:
sys.exit("ERROR: pass at least one of --lib or --srcs-file.")
sys.exit("ERROR: pass one of --lib, --srcs-file or "
"--no-artifact-hash.")
if args.source_only and not args.srcs_file:
sys.exit("ERROR: --source-only needs --srcs-file.")
if args.srcs_file and not os.path.isfile(args.srcs_file):
Expand Down
5 changes: 5 additions & 0 deletions tests/test_gen_sbom.py
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,11 @@ def test_dedup_keeps_last_assignment(self):
))
self.assertEqual(pairs['HAVE_X'], '2')

def test_missing_file_exits(self):
with self.assertRaises(SystemExit) as cm:
gs.parse_options_h('/no/such/options.h')
self.assertIn('/no/such/options.h', str(cm.exception))

def test_filters_compiler_internals_from_dm_e_dump(self):
# The no-pcpp escape hatch (`$CC -dM -E -include settings.h ...`)
# produces a defines file containing hundreds of host/compiler
Expand Down
17 changes: 17 additions & 0 deletions tests/test_sbom.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import importlib.util
import json
import os
import shutil
import subprocess
import sys
import tempfile
Expand Down Expand Up @@ -267,6 +268,22 @@ def unit_tests():
capture_output=True, text=True)
check(r.returncode != 0 and "stands alone" in r.stderr,
"no-artifact-hash rejects --srcs-file")
r = subprocess.run(base, capture_output=True, text=True)
check(r.returncode != 0
and "--lib, --srcs-file or --no-artifact-hash" in r.stderr,
"a missing checksum source names all three options")

make = shutil.which("make")
if make:
with open(os.path.join(d, "Makefile"), "w") as f:
f.write("SBOM_NAME = t\nSBOM_VERSION = 1\n"
"SBOM_DRIVER = false\n"
f"include {os.path.join(SHARE, 'build', 'sbom.mk')}\n")
r = subprocess.run([make, "-C", d, "sbom", "SBOM_SRCS=a.c",
"SBOM_LIB=" + lib],
capture_output=True, text=True)
check(r.returncode != 0 and "but not both" in r.stdout + r.stderr,
"sbom.mk rejects SBOM_SRCS with SBOM_LIB")


def find_gen_sbom(explicit):
Expand Down
30 changes: 30 additions & 0 deletions tests/test_sbom_cmake_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,36 @@ def test_default_call_records_install_targets(self):
self.assertNotIn("--dep-openssl", text)
self.assertNotIn("--crypto-only", text)

def test_targets_with_lib_fails_at_configure(self):
for n, (targets, lib, error) in enumerate((
("TARGETS x", "${CMAKE_CURRENT_BINARY_DIR}/libx.a",
"set TARGETS or LIB, not both"),
("TARGETS x", "FOO_LIB-NOTFOUND", "LIB was not found"),
("", "FOO_LIB-NOTFOUND", "LIB was not found"))):
with self.subTest(targets=targets, lib=lib):
src = self.dir / f"src{n}"
src.mkdir()
(src / "x.c").write_text("int x(void) { return 1; }\n")
(src / "LICENSE").write_text("demo\n")
(src / "CMakeLists.txt").write_text(f"""
cmake_minimum_required(VERSION 3.16)
project(sbomtest C)
add_library(x STATIC x.c)
include("{BUILD / "sbom.cmake"}")
wolfssl_compliance_tooling_add_sbom(
NAME t
VERSION 1
{targets}
LIB {lib}
LICENSE ${{CMAKE_CURRENT_SOURCE_DIR}}/LICENSE)
""")
result = run([
CMAKE, "-S", str(src), "-B", str(self.dir / f"build{n}"),
"-G", "Unix Makefiles",
])
self.assertNotEqual(result.returncode, 0)
self.assertIn(error, result.stderr)

def test_wolftpm_style_install_depends_on_the_public_target(self):
# The helper target is not the public sbom target. install-sbom
# must wait for the target that writes the tag-value file.
Expand Down
Loading