mirror of
https://github.com/anchore/syft.git
synced 2026-10-11 21:57:22 +02:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ea37792f1 | ||
|
|
823723f510 |
@@ -70,27 +70,16 @@ func ToFormatModel(s sbom.SBOM) *cyclonedx.BOM {
|
||||
continue
|
||||
}
|
||||
metadata = &fileMetadata
|
||||
|
||||
// Digests
|
||||
var digests []file.Digest
|
||||
if digestsForLocation, exists := artifacts.FileDigests[coordinate]; exists {
|
||||
digests = digestsForLocation
|
||||
}
|
||||
|
||||
cdxHashes := digestsToHashes(digests)
|
||||
components = append(components, cyclonedx.Component{
|
||||
BOMRef: string(coordinate.ID()),
|
||||
Type: cyclonedx.ComponentTypeFile,
|
||||
Name: metadata.Path,
|
||||
Hashes: &cdxHashes,
|
||||
Hashes: slicePtr(digestsToHashes(artifacts.FileDigests[coordinate])),
|
||||
})
|
||||
}
|
||||
cdxBOM.Components = &components
|
||||
cdxBOM.Components = slicePtr(components)
|
||||
|
||||
dependencies := toDependencies(s.Relationships)
|
||||
if len(dependencies) > 0 {
|
||||
cdxBOM.Dependencies = &dependencies
|
||||
}
|
||||
cdxBOM.Dependencies = slicePtr(toDependencies(s.Relationships))
|
||||
|
||||
return cdxBOM
|
||||
}
|
||||
@@ -277,14 +266,7 @@ func toDependencies(relationships []artifact.Relationship) []cyclonedx.Dependenc
|
||||
func toBomProperties(srcMetadata source.Description) *[]cyclonedx.Property {
|
||||
metadata, ok := srcMetadata.Metadata.(source.ImageMetadata)
|
||||
if ok {
|
||||
props := helpers.EncodeProperties(metadata.Labels, "syft:image:labels")
|
||||
// return nil if props is nil to avoid creating a pointer to a nil slice,
|
||||
// which results in a null JSON value that does not comply with the CycloneDX schema.
|
||||
// https://github.com/anchore/grype/issues/1759
|
||||
if props == nil {
|
||||
return nil
|
||||
}
|
||||
return &props
|
||||
return slicePtr(helpers.EncodeProperties(metadata.Labels, "syft:image:labels"))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -344,3 +326,14 @@ func toBomDescriptorComponent(srcMetadata source.Description) *cyclonedx.Compone
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Every slice pointer needs to either be a valid slice or nil,
|
||||
// otherwise we will create a pointer that is not nil but references
|
||||
// a nil slice, which results in a `null` JSON value that does not
|
||||
// comply with the CycloneDX schema. See: https://github.com/anchore/grype/issues/1759
|
||||
func slicePtr[T any](values []T) *[]T {
|
||||
if len(values) == 0 {
|
||||
return nil
|
||||
}
|
||||
return &values
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/anchore/syft/syft/file"
|
||||
"github.com/anchore/syft/syft/format/internal/cyclonedxutil"
|
||||
"github.com/anchore/syft/syft/format/internal/testutil"
|
||||
"github.com/anchore/syft/syft/pkg"
|
||||
@@ -27,6 +28,31 @@ func getEncoder(t testing.TB) sbom.FormatEncoder {
|
||||
return enc
|
||||
}
|
||||
|
||||
func Test_noTypedNils(t *testing.T) {
|
||||
s := sbom.SBOM{
|
||||
Artifacts: sbom.Artifacts{
|
||||
FileMetadata: map[file.Coordinates]file.Metadata{},
|
||||
FileDigests: map[file.Coordinates][]file.Digest{},
|
||||
},
|
||||
}
|
||||
c := file.NewCoordinates("/dev/null", "123")
|
||||
s.Artifacts.FileMetadata[c] = file.Metadata{
|
||||
Path: "/dev/null",
|
||||
}
|
||||
s.Artifacts.FileDigests[c] = []file.Digest{}
|
||||
|
||||
enc, err := NewFormatEncoderWithConfig(EncoderConfig{
|
||||
Version: "1.6",
|
||||
Pretty: true,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
contents := bytes.Buffer{}
|
||||
err = enc.Encode(&contents, s)
|
||||
require.NoError(t, err)
|
||||
require.NotContains(t, contents.String(), `"hashes": null`)
|
||||
}
|
||||
|
||||
func TestPrettyOutput(t *testing.T) {
|
||||
run := func(opt bool) string {
|
||||
enc, err := NewFormatEncoderWithConfig(EncoderConfig{
|
||||
|
||||
Reference in New Issue
Block a user