github.com/lineaje-labs/syft@v0.98.1-0.20231227153149-9e393f60ff1b/syft/pkg/cataloger/golang/parse_go_binary_test.go (about)

     1  package golang
     2  
     3  import (
     4  	"bufio"
     5  	"io"
     6  	"os"
     7  	"os/exec"
     8  	"path/filepath"
     9  	"runtime/debug"
    10  	"strconv"
    11  	"syscall"
    12  	"testing"
    13  
    14  	"github.com/stretchr/testify/assert"
    15  	"github.com/stretchr/testify/require"
    16  
    17  	"github.com/anchore/syft/syft/file"
    18  	"github.com/anchore/syft/syft/pkg"
    19  	"github.com/lineaje-labs/syft/syft/internal/fileresolver"
    20  )
    21  
    22  // make will run the default make target for the given test fixture path
    23  func runMakeTarget(t *testing.T, fixtureName string) {
    24  	cwd, err := os.Getwd()
    25  	require.NoError(t, err)
    26  	fixtureDir := filepath.Join(cwd, "test-fixtures/", fixtureName)
    27  
    28  	t.Logf("Generating Fixture in %q", fixtureDir)
    29  
    30  	cmd := exec.Command("make")
    31  	cmd.Dir = fixtureDir
    32  
    33  	stderr, err := cmd.StderrPipe()
    34  	require.NoError(t, err)
    35  
    36  	stdout, err := cmd.StdoutPipe()
    37  	require.NoError(t, err)
    38  
    39  	err = cmd.Start()
    40  	require.NoError(t, err)
    41  
    42  	show := func(label string, reader io.ReadCloser) {
    43  		scanner := bufio.NewScanner(reader)
    44  		scanner.Split(bufio.ScanLines)
    45  		for scanner.Scan() {
    46  			t.Logf("%s: %s", label, scanner.Text())
    47  		}
    48  	}
    49  	go show("out", stdout)
    50  	go show("err", stderr)
    51  
    52  	if err := cmd.Wait(); err != nil {
    53  		if exiterr, ok := err.(*exec.ExitError); ok {
    54  			// The program has exited with an exit code != 0
    55  
    56  			// This works on both Unix and Windows. Although package
    57  			// syscall is generally platform dependent, WaitStatus is
    58  			// defined for both Unix and Windows and in both cases has
    59  			// an ExitStatus() method with the same signature.
    60  			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
    61  				if status.ExitStatus() != 0 {
    62  					t.Fatalf("failed to generate fixture: rc=%d", status.ExitStatus())
    63  				}
    64  			}
    65  		} else {
    66  			t.Fatalf("unable to get generate fixture result: %+v", err)
    67  		}
    68  	}
    69  }
    70  
    71  func Test_getGOARCHFromBin(t *testing.T) {
    72  	runMakeTarget(t, "archs")
    73  
    74  	tests := []struct {
    75  		name     string
    76  		filepath string
    77  		expected string
    78  	}{
    79  		{
    80  			name:     "pe",
    81  			filepath: "test-fixtures/archs/binaries/hello-win-amd64",
    82  			// see: https://docs.microsoft.com/en-us/windows/win32/debug/pe-format#machine-types
    83  			expected: strconv.Itoa(0x8664),
    84  		},
    85  		{
    86  			name:     "elf-ppc64",
    87  			filepath: "test-fixtures/archs/binaries/hello-linux-ppc64le",
    88  			expected: "ppc64",
    89  		},
    90  		{
    91  			name:     "mach-o-arm64",
    92  			filepath: "test-fixtures/archs/binaries/hello-mach-o-arm64",
    93  			expected: "arm64",
    94  		},
    95  		{
    96  			name:     "linux-arm",
    97  			filepath: "test-fixtures/archs/binaries/hello-linux-arm",
    98  			expected: "arm",
    99  		},
   100  		{
   101  			name:     "xcoff-32bit",
   102  			filepath: "internal/xcoff/testdata/gcc-ppc32-aix-dwarf2-exec",
   103  			expected: strconv.Itoa(0x1DF),
   104  		},
   105  		{
   106  			name:     "xcoff-64bit",
   107  			filepath: "internal/xcoff/testdata/gcc-ppc64-aix-dwarf2-exec",
   108  			expected: strconv.Itoa(0x1F7),
   109  		},
   110  	}
   111  
   112  	for _, tt := range tests {
   113  		f, err := os.Open(tt.filepath)
   114  		require.NoError(t, err)
   115  		arch, err := getGOARCHFromBin(f)
   116  		require.NoError(t, err, "test name: %s", tt.name)
   117  		assert.Equal(t, tt.expected, arch)
   118  	}
   119  
   120  }
   121  
   122  func TestBuildGoPkgInfo(t *testing.T) {
   123  	const (
   124  		goCompiledVersion = "1.18"
   125  		archDetails       = "amd64"
   126  	)
   127  	defaultBuildSettings := map[string]string{
   128  		"GOARCH":  "amd64",
   129  		"GOOS":    "darwin",
   130  		"GOAMD64": "v1",
   131  	}
   132  
   133  	unmodifiedMain := pkg.Package{
   134  		Name:     "github.com/anchore/syft",
   135  		Language: pkg.Go,
   136  		Type:     pkg.GoModulePkg,
   137  		Version:  "(devel)",
   138  		PURL:     "pkg:golang/github.com/anchore/syft@(devel)",
   139  		Locations: file.NewLocationSet(
   140  			file.NewLocationFromCoordinates(
   141  				file.Coordinates{
   142  					RealPath:     "/a-path",
   143  					FileSystemID: "layer-id",
   144  				},
   145  			).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   146  		),
   147  		Metadata: pkg.GolangBinaryBuildinfoEntry{
   148  			GoCompiledVersion: goCompiledVersion,
   149  			Architecture:      archDetails,
   150  			BuildSettings:     defaultBuildSettings,
   151  			MainModule:        "github.com/anchore/syft",
   152  		},
   153  	}
   154  
   155  	tests := []struct {
   156  		name     string
   157  		mod      *extendedBuildInfo
   158  		expected []pkg.Package
   159  	}{
   160  		{
   161  			name: "package without name",
   162  			mod: &extendedBuildInfo{
   163  				BuildInfo: &debug.BuildInfo{
   164  					Deps: []*debug.Module{
   165  						{
   166  							Path: "github.com/adrg/xdg",
   167  						},
   168  						{
   169  							Path:    "",
   170  							Version: "v0.2.1",
   171  						},
   172  					},
   173  				},
   174  				cryptoSettings: nil,
   175  				arch:           "",
   176  			},
   177  			expected: []pkg.Package{
   178  				{
   179  					Name:     "github.com/adrg/xdg",
   180  					PURL:     "pkg:golang/github.com/adrg/xdg",
   181  					Language: pkg.Go,
   182  					Type:     pkg.GoModulePkg,
   183  					Locations: file.NewLocationSet(
   184  						file.NewLocationFromCoordinates(
   185  							file.Coordinates{
   186  								RealPath:     "/a-path",
   187  								FileSystemID: "layer-id",
   188  							},
   189  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   190  					),
   191  					Metadata: pkg.GolangBinaryBuildinfoEntry{},
   192  				},
   193  			},
   194  		},
   195  		{
   196  			name:     "buildGoPkgInfo parses a blank mod and returns no packages",
   197  			mod:      &extendedBuildInfo{&debug.BuildInfo{}, nil, ""},
   198  			expected: []pkg.Package(nil),
   199  		},
   200  		{
   201  			name: "parse a mod without main module",
   202  			mod: &extendedBuildInfo{
   203  				BuildInfo: &debug.BuildInfo{
   204  					GoVersion: goCompiledVersion,
   205  					Settings: []debug.BuildSetting{
   206  						{Key: "GOARCH", Value: archDetails},
   207  						{Key: "GOOS", Value: "darwin"},
   208  						{Key: "GOAMD64", Value: "v1"},
   209  					},
   210  					Deps: []*debug.Module{
   211  						{
   212  							Path:    "github.com/adrg/xdg",
   213  							Version: "v0.2.1",
   214  							Sum:     "h1:VSVdnH7cQ7V+B33qSJHTCRlNgra1607Q8PzEmnvb2Ic=",
   215  						},
   216  					},
   217  				},
   218  				cryptoSettings: nil,
   219  				arch:           archDetails,
   220  			},
   221  			expected: []pkg.Package{
   222  				{
   223  					Name:     "github.com/adrg/xdg",
   224  					Version:  "v0.2.1",
   225  					PURL:     "pkg:golang/github.com/adrg/xdg@v0.2.1",
   226  					Language: pkg.Go,
   227  					Type:     pkg.GoModulePkg,
   228  					Locations: file.NewLocationSet(
   229  						file.NewLocationFromCoordinates(
   230  							file.Coordinates{
   231  								RealPath:     "/a-path",
   232  								FileSystemID: "layer-id",
   233  							},
   234  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   235  					),
   236  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   237  						GoCompiledVersion: goCompiledVersion,
   238  						Architecture:      archDetails,
   239  						H1Digest:          "h1:VSVdnH7cQ7V+B33qSJHTCRlNgra1607Q8PzEmnvb2Ic=",
   240  					},
   241  				},
   242  			},
   243  		},
   244  		{
   245  			name: "parse a mod with path but no main module",
   246  			mod: &extendedBuildInfo{
   247  				BuildInfo: &debug.BuildInfo{
   248  					GoVersion: goCompiledVersion,
   249  					Settings: []debug.BuildSetting{
   250  						{Key: "GOARCH", Value: archDetails},
   251  						{Key: "GOOS", Value: "darwin"},
   252  						{Key: "GOAMD64", Value: "v1"},
   253  					},
   254  					Path: "github.com/a/b/c",
   255  				},
   256  				cryptoSettings: []string{"boringcrypto + fips"},
   257  				arch:           archDetails,
   258  			},
   259  			expected: []pkg.Package{
   260  				{
   261  					Name:     "github.com/a/b/c",
   262  					Version:  "(devel)",
   263  					PURL:     "pkg:golang/github.com/a/b/c@(devel)",
   264  					Language: pkg.Go,
   265  					Type:     pkg.GoModulePkg,
   266  					Locations: file.NewLocationSet(
   267  						file.NewLocationFromCoordinates(
   268  							file.Coordinates{
   269  								RealPath:     "/a-path",
   270  								FileSystemID: "layer-id",
   271  							},
   272  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   273  					),
   274  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   275  						GoCompiledVersion: goCompiledVersion,
   276  						Architecture:      archDetails,
   277  						H1Digest:          "",
   278  						BuildSettings: map[string]string{
   279  							"GOAMD64": "v1",
   280  							"GOARCH":  "amd64",
   281  							"GOOS":    "darwin",
   282  						},
   283  						MainModule:       "github.com/a/b/c",
   284  						GoCryptoSettings: []string{"boringcrypto + fips"},
   285  					},
   286  				},
   287  			},
   288  		},
   289  		{
   290  			name: "parse a mod without packages",
   291  			mod: &extendedBuildInfo{
   292  				BuildInfo: &debug.BuildInfo{
   293  					GoVersion: goCompiledVersion,
   294  					Main:      debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
   295  					Settings: []debug.BuildSetting{
   296  						{Key: "GOARCH", Value: archDetails},
   297  						{Key: "GOOS", Value: "darwin"},
   298  						{Key: "GOAMD64", Value: "v1"},
   299  					},
   300  				},
   301  				cryptoSettings: nil,
   302  				arch:           archDetails,
   303  			},
   304  			expected: []pkg.Package{unmodifiedMain},
   305  		},
   306  		{
   307  			name: "parse main mod and replace devel pseudo version and ldflags exists (but contains no version)",
   308  			mod: &extendedBuildInfo{
   309  				BuildInfo: &debug.BuildInfo{
   310  					GoVersion: goCompiledVersion,
   311  					Main:      debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
   312  					Settings: []debug.BuildSetting{
   313  						{Key: "GOARCH", Value: archDetails},
   314  						{Key: "GOOS", Value: "darwin"},
   315  						{Key: "GOAMD64", Value: "v1"},
   316  						{Key: "vcs.revision", Value: "41bc6bb410352845f22766e27dd48ba93aa825a4"},
   317  						{Key: "vcs.time", Value: "2022-10-14T19:54:57Z"},
   318  						{Key: "-ldflags", Value: `build	-ldflags="-w -s -extldflags '-static' -X blah=foobar`},
   319  					},
   320  				},
   321  				cryptoSettings: nil,
   322  				arch:           archDetails,
   323  			},
   324  			expected: []pkg.Package{
   325  				{
   326  					Name:     "github.com/anchore/syft",
   327  					Language: pkg.Go,
   328  					Type:     pkg.GoModulePkg,
   329  					Version:  "v0.0.0-20221014195457-41bc6bb41035",
   330  					PURL:     "pkg:golang/github.com/anchore/syft@v0.0.0-20221014195457-41bc6bb41035",
   331  					Locations: file.NewLocationSet(
   332  						file.NewLocationFromCoordinates(
   333  							file.Coordinates{
   334  								RealPath:     "/a-path",
   335  								FileSystemID: "layer-id",
   336  							},
   337  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   338  					),
   339  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   340  						GoCompiledVersion: goCompiledVersion,
   341  						Architecture:      archDetails,
   342  						BuildSettings: map[string]string{
   343  							"GOARCH":       archDetails,
   344  							"GOOS":         "darwin",
   345  							"GOAMD64":      "v1",
   346  							"vcs.revision": "41bc6bb410352845f22766e27dd48ba93aa825a4",
   347  							"vcs.time":     "2022-10-14T19:54:57Z",
   348  							"-ldflags":     `build	-ldflags="-w -s -extldflags '-static' -X blah=foobar`,
   349  						},
   350  						MainModule: "github.com/anchore/syft",
   351  					},
   352  				},
   353  			},
   354  		},
   355  		{
   356  			name: "parse main mod and replace devel version with one from ldflags with vcs. build settings",
   357  			mod: &extendedBuildInfo{
   358  				BuildInfo: &debug.BuildInfo{
   359  					GoVersion: goCompiledVersion,
   360  					Main:      debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
   361  					Settings: []debug.BuildSetting{
   362  						{Key: "GOARCH", Value: archDetails},
   363  						{Key: "GOOS", Value: "darwin"},
   364  						{Key: "GOAMD64", Value: "v1"},
   365  						{Key: "vcs.revision", Value: "41bc6bb410352845f22766e27dd48ba93aa825a4"},
   366  						{Key: "vcs.time", Value: "2022-10-14T19:54:57Z"},
   367  						{Key: "-ldflags", Value: `build	-ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0`},
   368  					},
   369  				},
   370  				cryptoSettings: nil,
   371  				arch:           archDetails,
   372  			},
   373  			expected: []pkg.Package{
   374  				{
   375  					Name:     "github.com/anchore/syft",
   376  					Language: pkg.Go,
   377  					Type:     pkg.GoModulePkg,
   378  					Version:  "v0.79.0",
   379  					PURL:     "pkg:golang/github.com/anchore/syft@v0.79.0",
   380  					Locations: file.NewLocationSet(
   381  						file.NewLocationFromCoordinates(
   382  							file.Coordinates{
   383  								RealPath:     "/a-path",
   384  								FileSystemID: "layer-id",
   385  							},
   386  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   387  					),
   388  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   389  						GoCompiledVersion: goCompiledVersion,
   390  						Architecture:      archDetails,
   391  						BuildSettings: map[string]string{
   392  							"GOARCH":       archDetails,
   393  							"GOOS":         "darwin",
   394  							"GOAMD64":      "v1",
   395  							"vcs.revision": "41bc6bb410352845f22766e27dd48ba93aa825a4",
   396  							"vcs.time":     "2022-10-14T19:54:57Z",
   397  							"-ldflags":     `build	-ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0`,
   398  						},
   399  						MainModule: "github.com/anchore/syft",
   400  					},
   401  				},
   402  			},
   403  		},
   404  		{
   405  			name: "parse main mod and replace devel version with one from ldflags without any vcs. build settings",
   406  			mod: &extendedBuildInfo{
   407  				BuildInfo: &debug.BuildInfo{
   408  					GoVersion: goCompiledVersion,
   409  					Main:      debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
   410  					Settings: []debug.BuildSetting{
   411  						{Key: "GOARCH", Value: archDetails},
   412  						{Key: "GOOS", Value: "darwin"},
   413  						{Key: "GOAMD64", Value: "v1"},
   414  						{Key: "-ldflags", Value: `build	-ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0`},
   415  					},
   416  				},
   417  				cryptoSettings: nil,
   418  				arch:           archDetails,
   419  			},
   420  			expected: []pkg.Package{
   421  				{
   422  					Name:     "github.com/anchore/syft",
   423  					Language: pkg.Go,
   424  					Type:     pkg.GoModulePkg,
   425  					Version:  "v0.79.0",
   426  					PURL:     "pkg:golang/github.com/anchore/syft@v0.79.0",
   427  					Locations: file.NewLocationSet(
   428  						file.NewLocationFromCoordinates(
   429  							file.Coordinates{
   430  								RealPath:     "/a-path",
   431  								FileSystemID: "layer-id",
   432  							},
   433  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   434  					),
   435  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   436  						GoCompiledVersion: goCompiledVersion,
   437  						Architecture:      archDetails,
   438  						BuildSettings: map[string]string{
   439  							"GOARCH":   archDetails,
   440  							"GOOS":     "darwin",
   441  							"GOAMD64":  "v1",
   442  							"-ldflags": `build	-ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0`,
   443  						},
   444  						MainModule: "github.com/anchore/syft",
   445  					},
   446  				},
   447  			},
   448  		},
   449  		{
   450  			name: "parse main mod and replace devel version with one from ldflags main.version without any vcs. build settings",
   451  			mod: &extendedBuildInfo{
   452  				BuildInfo: &debug.BuildInfo{
   453  					GoVersion: goCompiledVersion,
   454  					Main:      debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
   455  					Settings: []debug.BuildSetting{
   456  						{Key: "GOARCH", Value: archDetails},
   457  						{Key: "GOOS", Value: "darwin"},
   458  						{Key: "GOAMD64", Value: "v1"},
   459  						{Key: "-ldflags", Value: `build	-ldflags="-w -s -extldflags '-static' -X main.version=0.79.0`},
   460  					},
   461  				},
   462  				cryptoSettings: nil,
   463  				arch:           archDetails,
   464  			},
   465  			expected: []pkg.Package{
   466  				{
   467  					Name:     "github.com/anchore/syft",
   468  					Language: pkg.Go,
   469  					Type:     pkg.GoModulePkg,
   470  					Version:  "v0.79.0",
   471  					PURL:     "pkg:golang/github.com/anchore/syft@v0.79.0",
   472  					Locations: file.NewLocationSet(
   473  						file.NewLocationFromCoordinates(
   474  							file.Coordinates{
   475  								RealPath:     "/a-path",
   476  								FileSystemID: "layer-id",
   477  							},
   478  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   479  					),
   480  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   481  						GoCompiledVersion: goCompiledVersion,
   482  						Architecture:      archDetails,
   483  						BuildSettings: map[string]string{
   484  							"GOARCH":   archDetails,
   485  							"GOOS":     "darwin",
   486  							"GOAMD64":  "v1",
   487  							"-ldflags": `build	-ldflags="-w -s -extldflags '-static' -X main.version=0.79.0`,
   488  						},
   489  						MainModule: "github.com/anchore/syft",
   490  					},
   491  				},
   492  			},
   493  		},
   494  		{
   495  			name: "parse main mod and replace devel version with one from ldflags main.Version without any vcs. build settings",
   496  			mod: &extendedBuildInfo{
   497  				BuildInfo: &debug.BuildInfo{
   498  					GoVersion: goCompiledVersion,
   499  					Main:      debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
   500  					Settings: []debug.BuildSetting{
   501  						{Key: "GOARCH", Value: archDetails},
   502  						{Key: "GOOS", Value: "darwin"},
   503  						{Key: "GOAMD64", Value: "v1"},
   504  						{Key: "-ldflags", Value: `build	-ldflags="-w -s -extldflags '-static' -X main.Version=0.79.0`},
   505  					},
   506  				},
   507  				cryptoSettings: nil,
   508  				arch:           archDetails,
   509  			},
   510  			expected: []pkg.Package{
   511  				{
   512  					Name:     "github.com/anchore/syft",
   513  					Language: pkg.Go,
   514  					Type:     pkg.GoModulePkg,
   515  					Version:  "v0.79.0",
   516  					PURL:     "pkg:golang/github.com/anchore/syft@v0.79.0",
   517  					Locations: file.NewLocationSet(
   518  						file.NewLocationFromCoordinates(
   519  							file.Coordinates{
   520  								RealPath:     "/a-path",
   521  								FileSystemID: "layer-id",
   522  							},
   523  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   524  					),
   525  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   526  						GoCompiledVersion: goCompiledVersion,
   527  						Architecture:      archDetails,
   528  						BuildSettings: map[string]string{
   529  							"GOARCH":   archDetails,
   530  							"GOOS":     "darwin",
   531  							"GOAMD64":  "v1",
   532  							"-ldflags": `build	-ldflags="-w -s -extldflags '-static' -X main.Version=0.79.0`,
   533  						},
   534  						MainModule: "github.com/anchore/syft",
   535  					},
   536  				},
   537  			},
   538  		},
   539  		{
   540  			name: "parse main mod and replace devel version with a pseudo version",
   541  			mod: &extendedBuildInfo{
   542  				BuildInfo: &debug.BuildInfo{
   543  					GoVersion: goCompiledVersion,
   544  					Main:      debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
   545  					Settings: []debug.BuildSetting{
   546  						{Key: "GOARCH", Value: archDetails},
   547  						{Key: "GOOS", Value: "darwin"},
   548  						{Key: "GOAMD64", Value: "v1"},
   549  						{Key: "vcs.revision", Value: "41bc6bb410352845f22766e27dd48ba93aa825a4"},
   550  						{Key: "vcs.time", Value: "2022-10-14T19:54:57Z"},
   551  					},
   552  				},
   553  				cryptoSettings: nil,
   554  				arch:           archDetails,
   555  			},
   556  			expected: []pkg.Package{
   557  				{
   558  					Name:     "github.com/anchore/syft",
   559  					Language: pkg.Go,
   560  					Type:     pkg.GoModulePkg,
   561  					Version:  "v0.0.0-20221014195457-41bc6bb41035",
   562  					PURL:     "pkg:golang/github.com/anchore/syft@v0.0.0-20221014195457-41bc6bb41035",
   563  					Locations: file.NewLocationSet(
   564  						file.NewLocationFromCoordinates(
   565  							file.Coordinates{
   566  								RealPath:     "/a-path",
   567  								FileSystemID: "layer-id",
   568  							},
   569  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   570  					),
   571  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   572  						GoCompiledVersion: goCompiledVersion,
   573  						Architecture:      archDetails,
   574  						BuildSettings: map[string]string{
   575  							"GOARCH":       archDetails,
   576  							"GOOS":         "darwin",
   577  							"GOAMD64":      "v1",
   578  							"vcs.revision": "41bc6bb410352845f22766e27dd48ba93aa825a4",
   579  							"vcs.time":     "2022-10-14T19:54:57Z",
   580  						},
   581  						MainModule: "github.com/anchore/syft",
   582  					},
   583  				},
   584  			},
   585  		},
   586  		{
   587  			name: "parse a populated mod string and returns packages but no source info",
   588  			mod: &extendedBuildInfo{
   589  				BuildInfo: &debug.BuildInfo{
   590  					GoVersion: goCompiledVersion,
   591  					Main:      debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
   592  					Settings: []debug.BuildSetting{
   593  						{Key: "GOARCH", Value: archDetails},
   594  						{Key: "GOOS", Value: "darwin"},
   595  						{Key: "GOAMD64", Value: "v1"},
   596  					},
   597  					Deps: []*debug.Module{
   598  						{
   599  							Path:    "github.com/adrg/xdg",
   600  							Version: "v0.2.1",
   601  							Sum:     "h1:VSVdnH7cQ7V+B33qSJHTCRlNgra1607Q8PzEmnvb2Ic=",
   602  						},
   603  						{
   604  							Path:    "github.com/anchore/client-go",
   605  							Version: "v0.0.0-20210222170800-9c70f9b80bcf",
   606  							Sum:     "h1:DYssiUV1pBmKqzKsm4mqXx8artqC0Q8HgZsVI3lMsAg=",
   607  						},
   608  					},
   609  				},
   610  				cryptoSettings: nil,
   611  				arch:           archDetails,
   612  			},
   613  			expected: []pkg.Package{
   614  				{
   615  					Name:     "github.com/adrg/xdg",
   616  					Version:  "v0.2.1",
   617  					PURL:     "pkg:golang/github.com/adrg/xdg@v0.2.1",
   618  					Language: pkg.Go,
   619  					Type:     pkg.GoModulePkg,
   620  					Locations: file.NewLocationSet(
   621  						file.NewLocationFromCoordinates(
   622  							file.Coordinates{
   623  								RealPath:     "/a-path",
   624  								FileSystemID: "layer-id",
   625  							},
   626  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   627  					),
   628  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   629  						GoCompiledVersion: goCompiledVersion,
   630  						Architecture:      archDetails,
   631  						H1Digest:          "h1:VSVdnH7cQ7V+B33qSJHTCRlNgra1607Q8PzEmnvb2Ic=",
   632  						MainModule:        "github.com/anchore/syft",
   633  					},
   634  				},
   635  				{
   636  					Name:     "github.com/anchore/client-go",
   637  					Version:  "v0.0.0-20210222170800-9c70f9b80bcf",
   638  					PURL:     "pkg:golang/github.com/anchore/client-go@v0.0.0-20210222170800-9c70f9b80bcf",
   639  					Language: pkg.Go,
   640  					Type:     pkg.GoModulePkg,
   641  					Locations: file.NewLocationSet(
   642  						file.NewLocationFromCoordinates(
   643  							file.Coordinates{
   644  								RealPath:     "/a-path",
   645  								FileSystemID: "layer-id",
   646  							},
   647  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   648  					),
   649  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   650  						GoCompiledVersion: goCompiledVersion,
   651  						Architecture:      archDetails,
   652  						H1Digest:          "h1:DYssiUV1pBmKqzKsm4mqXx8artqC0Q8HgZsVI3lMsAg=",
   653  						MainModule:        "github.com/anchore/syft",
   654  					},
   655  				},
   656  				unmodifiedMain,
   657  			},
   658  		},
   659  		{
   660  			name: "parse a populated mod string and returns packages when a replace directive exists",
   661  			mod: &extendedBuildInfo{
   662  				BuildInfo: &debug.BuildInfo{
   663  					GoVersion: goCompiledVersion,
   664  					Main:      debug.Module{Path: "github.com/anchore/syft", Version: "(devel)"},
   665  					Settings: []debug.BuildSetting{
   666  						{Key: "GOARCH", Value: archDetails},
   667  						{Key: "GOOS", Value: "darwin"},
   668  						{Key: "GOAMD64", Value: "v1"},
   669  					},
   670  					Deps: []*debug.Module{
   671  						{
   672  							Path:    "golang.org/x/sys",
   673  							Version: "v0.0.0-20211006194710-c8a6f5223071",
   674  							Sum:     "h1:PjhxBct4MZii8FFR8+oeS7QOvxKOTZXgk63EU2XpfJE=",
   675  						},
   676  						{
   677  							Path:    "golang.org/x/term",
   678  							Version: "v0.0.0-20210927222741-03fcf44c2211",
   679  							Sum:     "h1:PjhxBct4MZii8FFR8+oeS7QOvxKOTZXgk63EU2XpfJE=",
   680  							Replace: &debug.Module{
   681  								Path:    "golang.org/x/term",
   682  								Version: "v0.0.0-20210916214954-140adaaadfaf",
   683  								Sum:     "h1:Ihq/mm/suC88gF8WFcVwk+OV6Tq+wyA1O0E5UEvDglI=",
   684  							},
   685  						},
   686  					},
   687  				},
   688  				cryptoSettings: nil,
   689  				arch:           archDetails,
   690  			},
   691  			expected: []pkg.Package{
   692  				{
   693  					Name:     "golang.org/x/sys",
   694  					Version:  "v0.0.0-20211006194710-c8a6f5223071",
   695  					PURL:     "pkg:golang/golang.org/x/sys@v0.0.0-20211006194710-c8a6f5223071",
   696  					Language: pkg.Go,
   697  					Type:     pkg.GoModulePkg,
   698  					Locations: file.NewLocationSet(
   699  						file.NewLocationFromCoordinates(
   700  							file.Coordinates{
   701  								RealPath:     "/a-path",
   702  								FileSystemID: "layer-id",
   703  							},
   704  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   705  					),
   706  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   707  						GoCompiledVersion: goCompiledVersion,
   708  						Architecture:      archDetails,
   709  						H1Digest:          "h1:PjhxBct4MZii8FFR8+oeS7QOvxKOTZXgk63EU2XpfJE=",
   710  						MainModule:        "github.com/anchore/syft",
   711  					}},
   712  				{
   713  					Name:     "golang.org/x/term",
   714  					Version:  "v0.0.0-20210916214954-140adaaadfaf",
   715  					PURL:     "pkg:golang/golang.org/x/term@v0.0.0-20210916214954-140adaaadfaf",
   716  					Language: pkg.Go,
   717  					Type:     pkg.GoModulePkg,
   718  					Locations: file.NewLocationSet(
   719  						file.NewLocationFromCoordinates(
   720  							file.Coordinates{
   721  								RealPath:     "/a-path",
   722  								FileSystemID: "layer-id",
   723  							},
   724  						).WithAnnotation(pkg.EvidenceAnnotationKey, pkg.PrimaryEvidenceAnnotation),
   725  					),
   726  					Metadata: pkg.GolangBinaryBuildinfoEntry{
   727  						GoCompiledVersion: goCompiledVersion,
   728  						Architecture:      archDetails,
   729  						H1Digest:          "h1:Ihq/mm/suC88gF8WFcVwk+OV6Tq+wyA1O0E5UEvDglI=",
   730  						MainModule:        "github.com/anchore/syft",
   731  					},
   732  				},
   733  				unmodifiedMain,
   734  			},
   735  		},
   736  	}
   737  
   738  	for _, test := range tests {
   739  		t.Run(test.name, func(t *testing.T) {
   740  			for i := range test.expected {
   741  				p := &test.expected[i]
   742  				p.SetID()
   743  			}
   744  			location := file.NewLocationFromCoordinates(
   745  				file.Coordinates{
   746  					RealPath:     "/a-path",
   747  					FileSystemID: "layer-id",
   748  				},
   749  			)
   750  
   751  			c := goBinaryCataloger{}
   752  			pkgs := c.buildGoPkgInfo(fileresolver.Empty{}, location, test.mod, test.mod.arch)
   753  			assert.Equal(t, test.expected, pkgs)
   754  		})
   755  	}
   756  }
   757  
   758  func Test_extractVersionFromLDFlags(t *testing.T) {
   759  	tests := []struct {
   760  		name             string
   761  		ldflags          string
   762  		wantMajorVersion string
   763  		wantFullVersion  string
   764  	}{
   765  		{
   766  			name:    "empty ldflags",
   767  			ldflags: "",
   768  		},
   769  		{
   770  			name:             "syft ldflags",
   771  			ldflags:          `	build	-ldflags="-w -s -extldflags '-static' -X github.com/anchore/syft/internal/version.version=0.79.0 -X github.com/anchore/syft/internal/version.gitCommit=b2b332e8b2b66af0905e98b54ebd713a922be1a8 -X github.com/anchore/syft/internal/version.buildDate=2023-04-21T16:20:25Z -X github.com/anchore/syft/internal/version.gitDescription=v0.79.0 "`,
   772  			wantMajorVersion: "0",
   773  			wantFullVersion:  "v0.79.0",
   774  		},
   775  		{
   776  			name: "kubectl ldflags",
   777  			ldflags: `	build	-asmflags=all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes
   778  	build	-compiler=gc
   779  	build	-gcflags="all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes "
   780  	build	-ldflags="all=-X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.buildDate=2023-04-12T12:16:51Z' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.buildDate=2023-04-12T12:16:51Z' -X 'k8s.io/client-go/pkg/version.buildDate=2023-04-12T12:16:51Z' -X 'k8s.io/component-base/version.buildDate=2023-04-12T12:16:51Z' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitCommit=a1a87a0a2bcd605820920c6b0e618a8ab7d117d4' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitCommit=a1a87a0a2bcd605820920c6b0e618a8ab7d117d4' -X 'k8s.io/client-go/pkg/version.gitCommit=a1a87a0a2bcd605820920c6b0e618a8ab7d117d4' -X 'k8s.io/component-base/version.gitCommit=a1a87a0a2bcd605820920c6b0e618a8ab7d117d4' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitTreeState=clean' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitTreeState=clean' -X 'k8s.io/client-go/pkg/version.gitTreeState=clean' -X 'k8s.io/component-base/version.gitTreeState=clean' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitVersion=v1.25.9' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitVersion=v1.25.9' -X 'k8s.io/client-go/pkg/version.gitVersion=v1.25.9' -X 'k8s.io/component-base/version.gitVersion=v1.25.9' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitMajor=1' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitMajor=1' -X 'k8s.io/client-go/pkg/version.gitMajor=1' -X 'k8s.io/component-base/version.gitMajor=1' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitMinor=25' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitMinor=25' -X 'k8s.io/client-go/pkg/version.gitMinor=25' -X 'k8s.io/component-base/version.gitMinor=25'  -s -w"`,
   781  			wantMajorVersion: "1",
   782  			wantFullVersion:  "v1.25.9",
   783  		},
   784  		{
   785  			name:             "nerdctl ldflags",
   786  			ldflags:          `	build	-ldflags="-s -w -X github.com/containerd/nerdctl/pkg/version.Version=v1.3.1 -X github.com/containerd/nerdctl/pkg/version.Revision=b224b280ff3086516763c7335fc0e0997aca617a"`,
   787  			wantMajorVersion: "1",
   788  			wantFullVersion:  "v1.3.1",
   789  		},
   790  		{
   791  			name:             "limactl ldflags",
   792  			ldflags:          `	build	-ldflags="-s -w -X github.com/lima-vm/lima/pkg/version.Version=v0.15.1"`,
   793  			wantMajorVersion: "0",
   794  			wantFullVersion:  "v0.15.1",
   795  		},
   796  		{
   797  			name:             "terraform ldflags",
   798  			ldflags:          `	build	-ldflags="-w -s -X 'github.com/hashicorp/terraform/version.Version=1.4.6' -X 'github.com/hashicorp/terraform/version.Prerelease='"`,
   799  			wantMajorVersion: "1",
   800  			wantFullVersion:  "v1.4.6",
   801  		},
   802  		{
   803  			name: "kube-apiserver ldflags",
   804  			ldflags: `	build	-asmflags=all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes
   805  	build	-buildmode=exe
   806  	build	-compiler=gc
   807  	build	-gcflags="all=-trimpath=/workspace/src/k8s.io/kubernetes/_output/dockerized/go/src/k8s.io/kubernetes "
   808  	build	-ldflags="all=-X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.buildDate=2023-04-14T13:14:42Z' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.buildDate=2023-04-14T13:14:42Z' -X 'k8s.io/client-go/pkg/version.buildDate=2023-04-14T13:14:42Z' -X 'k8s.io/component-base/version.buildDate=2023-04-14T13:14:42Z' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitCommit=4c9411232e10168d7b050c49a1b59f6df9d7ea4b' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitCommit=4c9411232e10168d7b050c49a1b59f6df9d7ea4b' -X 'k8s.io/client-go/pkg/version.gitCommit=4c9411232e10168d7b050c49a1b59f6df9d7ea4b' -X 'k8s.io/component-base/version.gitCommit=4c9411232e10168d7b050c49a1b59f6df9d7ea4b' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitTreeState=clean' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitTreeState=clean' -X 'k8s.io/client-go/pkg/version.gitTreeState=clean' -X 'k8s.io/component-base/version.gitTreeState=clean' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitVersion=v1.27.1' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitVersion=v1.27.1' -X 'k8s.io/client-go/pkg/version.gitVersion=v1.27.1' -X 'k8s.io/component-base/version.gitVersion=v1.27.1' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitMajor=1' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitMajor=1' -X 'k8s.io/client-go/pkg/version.gitMajor=1' -X 'k8s.io/component-base/version.gitMajor=1' -X 'k8s.io/kubernetes/vendor/k8s.io/client-go/pkg/version.gitMinor=27' -X 'k8s.io/kubernetes/vendor/k8s.io/component-base/version.gitMinor=27' -X 'k8s.io/client-go/pkg/version.gitMinor=27' -X 'k8s.io/component-base/version.gitMinor=27'  -s -w"`,
   809  			wantMajorVersion: "1",
   810  			wantFullVersion:  "v1.27.1",
   811  		},
   812  		{
   813  			name: "prometheus ldflags",
   814  			ldflags: `	build	-ldflags="-X github.com/prometheus/common/version.Version=2.44.0 -X github.com/prometheus/common/version.Revision=1ac5131f698ebc60f13fe2727f89b115a41f6558 -X github.com/prometheus/common/version.Branch=HEAD -X github.com/prometheus/common/version.BuildUser=root@739e8181c5db -X github.com/prometheus/common/version.BuildDate=20230514-06:18:11  -extldflags '-static'"
   815  	build	-tags=netgo,builtinassets,stringlabels`,
   816  			wantMajorVersion: "2",
   817  			wantFullVersion:  "v2.44.0",
   818  		},
   819  		{
   820  			name: "influxdb ldflags",
   821  			ldflags: `	build	-ldflags="-s -w -X main.version=v2.7.1 -X main.commit=407fa622e9 -X main.date=2023-04-28T13:24:27Z -linkmode=external -extld=/musl/x86_64/bin/musl-gcc -extldflags '-fno-PIC -static-pie -Wl,-z,stack-size=8388608'"
   822  	build	-tags=assets,sqlite_foreign_keys,sqlite_json,static_build,noasm`,
   823  			wantMajorVersion: "2",
   824  			wantFullVersion:  "v2.7.1",
   825  		},
   826  		{
   827  			name:             "gitea ldflags",
   828  			ldflags:          `	build	-ldflags=" -X \"main.MakeVersion=GNU Make 4.1\" -X \"main.Version=1.19.3\" -X \"main.Tags=bindata sqlite sqlite_unlock_notify\" "`,
   829  			wantMajorVersion: "1",
   830  			wantFullVersion:  "v1.19.3",
   831  		},
   832  		{
   833  			name:             "docker sbom cli ldflags",
   834  			ldflags:          `	build	-ldflags="-w -s -extldflags '-static' -X github.com/docker/sbom-cli-plugin/internal/version.version=0.6.1-SNAPSHOT-02cf1c8 -X github.com/docker/sbom-cli-plugin/internal/version.gitCommit=02cf1c888ad6662109ac6e3be618392514a56316 -X github.com/docker/sbom-cli-plugin/internal/version.gitDescription=v0.6.1-dirty "`,
   835  			wantMajorVersion: "0",
   836  			wantFullVersion:  "v0.6.1-SNAPSHOT-02cf1c8",
   837  		},
   838  		{
   839  			name:             "docker scout ldflags",
   840  			ldflags:          `	build	-ldflags="-w -s -extldflags '-static' -X github.com/docker/scout-cli-plugin/internal.version=0.10.0 "`,
   841  			wantMajorVersion: "0",
   842  			wantFullVersion:  "v0.10.0",
   843  		},
   844  		{
   845  			name:             "influx telegraf ldflags",
   846  			ldflags:          `	build	-ldflags="-w -s -X github.com/influxdata/telegraf/internal.Commit=a3a884a1 -X github.com/influxdata/telegraf/internal.Branch=HEAD -X github.com/influxdata/telegraf/internal.Version=1.26.2"`,
   847  			wantMajorVersion: "1",
   848  			wantFullVersion:  "v1.26.2",
   849  		},
   850  		{
   851  			name:             "argocd ldflags",
   852  			ldflags:          `	build	-ldflags="-X github.com/argoproj/argo-cd/v2/common.version=2.7.2 -X github.com/argoproj/argo-cd/v2/common.buildDate=2023-05-12T14:06:49Z -X github.com/argoproj/argo-cd/v2/common.gitCommit=cbee7e6011407ed2d1066c482db74e97e0cc6bdb -X github.com/argoproj/argo-cd/v2/common.gitTreeState=clean -X github.com/argoproj/argo-cd/v2/common.kubectlVersion=v0.24.2 -extldflags=\"-static\""`,
   853  			wantMajorVersion: "2",
   854  			wantFullVersion:  "v2.7.2",
   855  		},
   856  		{
   857  			name:             "kustomize ldflags",
   858  			ldflags:          `	build	-ldflags="-s -X sigs.k8s.io/kustomize/api/provenance.version=kustomize/v4.5.7 -X sigs.k8s.io/kustomize/api/provenance.gitCommit=56d82a8378dfc8dc3b3b1085e5a6e67b82966bd7 -X sigs.k8s.io/kustomize/api/provenance.buildDate=2022-08-02T16:35:54Z "`,
   859  			wantMajorVersion: "4",
   860  			wantFullVersion:  "v4.5.7",
   861  		},
   862  		// ////////////////////////////////////////////////////////////////
   863  		// negative cases
   864  		{
   865  			name:    "hugo ldflags",
   866  			ldflags: `	build	-ldflags="-s -w -X github.com/gohugoio/hugo/common/hugo.vendorInfo=gohugoio"`,
   867  		},
   868  		{
   869  			name:    "ghostunnel ldflags",
   870  			ldflags: `	build	-ldflags="-X main.version=77d9aaa"`,
   871  		},
   872  		{
   873  			name:    "opa ldflags",
   874  			ldflags: `build	-ldflags=" -X github.com/open-policy-agent/opa/version.Hostname=9549178459bc"`,
   875  		},
   876  		// /////////////////////////////////////////////////////////////////
   877  		// trickier cases
   878  		{
   879  			name:             "macvlan plugin for cri-o ldflags",
   880  			ldflags:          `	build	-ldflags="-extldflags -static -X github.com/containernetworking/plugins/pkg/utils/buildversion.BuildVersion=v1.2.0"`,
   881  			wantMajorVersion: "1",
   882  			wantFullVersion:  "v1.2.0",
   883  		},
   884  		{
   885  			name:             "coder ldflags",
   886  			ldflags:          `	build	-ldflags="-s -w -X 'github.com/coder/coder/buildinfo.tag=0.23.4'"`,
   887  			wantMajorVersion: "0",
   888  			wantFullVersion:  "v0.23.4",
   889  		},
   890  		// /////////////////////////////////////////////////////////////////
   891  		// don't know how to handle these... yet
   892  		// {
   893  		//	// package name: pkgName: "github.com/krakendio/krakend-ce/v2",
   894  		//	name:             "krakenD ldflags",
   895  		//	ldflags:          `	build	-ldflags="-X github.com/luraproject/lura/v2/core.KrakendVersion=2.3.2 -X github.com/luraproject/lura/v2/core.GoVersion=1.20.4 -X github.com/luraproject/lura/v2/core.GlibcVersion=GLIBC-2.31_(debian-11) "`,
   896  		//	wantMajorVersion: "2.3.2",
   897  		//	wantFullVersion:  "v2.3.2",
   898  		// },
   899  		// {
   900  		//	// package name: pkgName: "github.com/krakendio/krakend-ce/v2",
   901  		//	name:             "krakenD ldflags -- answer embedded in the middle",
   902  		//	ldflags:          `	build	-ldflags=" -X github.com/luraproject/lura/v2/core.GoVersion=1.20.4 -X github.com/luraproject/lura/v2/core.KrakendVersion=2.3.2 -X github.com/luraproject/lura/v2/core.GlibcVersion=GLIBC-2.31_(debian-11) "`,
   903  		//	wantMajorVersion: "2.3.2",
   904  		//	wantFullVersion:  "v2.3.2",
   905  		// },
   906  	}
   907  	for _, tt := range tests {
   908  		t.Run(tt.name, func(t *testing.T) {
   909  			gotMajorVersion, gotFullVersion := extractVersionFromLDFlags(tt.ldflags)
   910  			assert.Equal(t, tt.wantMajorVersion, gotMajorVersion, "unexpected major version")
   911  			assert.Equal(t, tt.wantFullVersion, gotFullVersion, "unexpected full version")
   912  		})
   913  	}
   914  }