From 95c73781098dc388868bd845cc1c00e88d736a7f Mon Sep 17 00:00:00 2001 From: Keith Zantow Date: Tue, 1 Nov 2022 17:26:00 -0400 Subject: [PATCH] fix: Decode binary and unknown metadata (#1307) --- syft/formats/syftjson/model/package.go | 134 +++----------------- syft/formats/syftjson/model/package_test.go | 20 +++ 2 files changed, 38 insertions(+), 116 deletions(-) diff --git a/syft/formats/syftjson/model/package.go b/syft/formats/syftjson/model/package.go index b2fd91903..67d9cc8b8 100644 --- a/syft/formats/syftjson/model/package.go +++ b/syft/formats/syftjson/model/package.go @@ -4,6 +4,7 @@ import ( "encoding/json" "errors" "fmt" + "reflect" "github.com/anchore/syft/internal/log" "github.com/anchore/syft/syft/pkg" @@ -71,130 +72,31 @@ func (p *Package) UnmarshalJSON(b []byte) error { return err } -//nolint:funlen,gocognit,gocyclo func unpackMetadata(p *Package, unpacker packageMetadataUnpacker) error { p.MetadataType = pkg.CleanMetadataType(unpacker.MetadataType) - switch p.MetadataType { - case "": - // there is no metadata, skip - break - case pkg.AlpmMetadataType: - var payload pkg.AlpmMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + typ, ok := pkg.MetadataTypeByName[p.MetadataType] + if ok { + val := reflect.New(typ).Interface() + if err := json.Unmarshal(unpacker.Metadata, val); err != nil { return err } - p.Metadata = payload - case pkg.ApkMetadataType: - var payload pkg.ApkMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { + p.Metadata = reflect.ValueOf(val).Elem().Interface() + return nil + } + + // capture unknown metadata as a generic struct + if len(unpacker.Metadata) > 0 { + var val interface{} + if err := json.Unmarshal(unpacker.Metadata, &val); err != nil { return err } - p.Metadata = payload - case pkg.RpmMetadataType: - var payload pkg.RpmMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.DpkgMetadataType: - var payload pkg.DpkgMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.JavaMetadataType: - var payload pkg.JavaMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.RustCargoPackageMetadataType: - var payload pkg.CargoPackageMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.GemMetadataType: - var payload pkg.GemMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.KbPackageMetadataType: - var payload pkg.KbPackageMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.PythonPackageMetadataType: - var payload pkg.PythonPackageMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.NpmPackageJSONMetadataType: - var payload pkg.NpmPackageJSONMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.PhpComposerJSONMetadataType: - var payload pkg.PhpComposerJSONMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.GolangBinMetadataType: - var payload pkg.GolangBinMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.DartPubMetadataType: - var payload pkg.DartPubMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.CocoapodsMetadataType: - var payload pkg.CocoapodsMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.ConanMetadataType: - var payload pkg.ConanMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.ConanLockMetadataType: - var payload pkg.ConanLockMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.DotnetDepsMetadataType: - var payload pkg.DotnetDepsMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.PortageMetadataType: - var payload pkg.PortageMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - case pkg.HackageMetadataType: - var payload pkg.HackageMetadata - if err := json.Unmarshal(unpacker.Metadata, &payload); err != nil { - return err - } - p.Metadata = payload - default: + p.Metadata = val + } + + if p.MetadataType != "" { return errUnknownMetadataType } + return nil } diff --git a/syft/formats/syftjson/model/package_test.go b/syft/formats/syftjson/model/package_test.go index 0887a4e0a..eb57dbbc0 100644 --- a/syft/formats/syftjson/model/package_test.go +++ b/syft/formats/syftjson/model/package_test.go @@ -2,6 +2,7 @@ package model import ( "encoding/json" + "reflect" "testing" "github.com/stretchr/testify/assert" @@ -87,6 +88,7 @@ func Test_unpackMetadata(t *testing.T) { name string packageData []byte metadataType pkg.MetadataType + wantMetadata interface{} wantErr require.ErrorAssertionFunc }{ { @@ -196,6 +198,20 @@ func Test_unpackMetadata(t *testing.T) { "metadataType": "BOGOSITY" }`), }, + { + name: "unknown metadata type", + packageData: []byte(`{ + "metadataType": "NewMetadataType", + "metadata": { + "thing": "thing-1" + } + }`), + wantErr: require.Error, + metadataType: "NewMetadataType", + wantMetadata: map[string]interface{}{ + "thing": "thing-1", + }, + }, } for _, test := range tests { @@ -215,6 +231,10 @@ func Test_unpackMetadata(t *testing.T) { err := unpackMetadata(p, unpacker) assert.Equal(t, test.metadataType, p.MetadataType) test.wantErr(t, err) + + if test.wantMetadata != nil { + assert.True(t, reflect.DeepEqual(test.wantMetadata, p.Metadata)) + } }) } }