From ef73beff3d939331d80f9084a38f4f1cfa20a71b Mon Sep 17 00:00:00 2001 From: "Mikhail f. Shiryaev" Date: Wed, 9 Feb 2022 03:59:04 +0100 Subject: [PATCH 1/4] fix: issue with symlinks in directories for nfpm --- glob.go | 8 ++++++++ glob_test.go | 24 ++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/glob.go b/glob.go index d2df9b7..bcbcf6e 100644 --- a/glob.go +++ b/glob.go @@ -124,6 +124,14 @@ func Glob(pattern string, opts ...OptFunc) ([]string, error) { // nolint:funlen, return nil, fmt.Errorf("cannot determine static prefix: %w", err) } + // Check if the file is valid symlink without following it + // It works only for valid absolut or relative file paths, in other words, will fail for WithFs() option + if patternInfo, err := os.Lstat(pattern); err == nil { + if patternInfo.Mode()&os.ModeSymlink == os.ModeSymlink { + return cleanFilepaths([]string{pattern}, options.prefix), nil + } + } + prefixInfo, err := fs.Stat(options.fs, prefix) if errors.Is(err, fs.ErrNotExist) { if !ContainsMatchers(pattern) { diff --git a/glob_test.go b/glob_test.go index 9831f2a..a5dfb44 100644 --- a/glob_test.go +++ b/glob_test.go @@ -450,6 +450,30 @@ func TestGlob(t *testing.T) { // nolint:funlen "a/b/4.txt", }, matches) }) + + t.Run("symlinks", func(t *testing.T) { + t.Parallel() + testFS := testFs(t, []string{ + "./a/file", + }, nil).(testfs.FS) + + fsPath := testFS.Path() + workingSymlink := filepath.Join(fsPath, "b") + brokenSymlink := filepath.Join(fsPath, "c") + os.Symlink("a", workingSymlink) + os.Symlink("non-existent", brokenSymlink) + + matches, err := Glob(workingSymlink) + require.NoError(t, err) + require.Equal(t, []string{ + workingSymlink, + }, matches) + matches, err = Glob(brokenSymlink) + require.NoError(t, err) + require.Equal(t, []string{ + brokenSymlink, + }, matches) + }) } func TestQuoteMeta(t *testing.T) { From 0de20e84651ccd4187ceeda299625bdc3bc4960b Mon Sep 17 00:00:00 2001 From: "Mikhail f. Shiryaev" Date: Wed, 9 Feb 2022 14:26:28 +0100 Subject: [PATCH 2/4] test: add NoErr checks for os.Symlink calls --- glob_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/glob_test.go b/glob_test.go index a5dfb44..53dbbd4 100644 --- a/glob_test.go +++ b/glob_test.go @@ -460,8 +460,10 @@ func TestGlob(t *testing.T) { // nolint:funlen fsPath := testFS.Path() workingSymlink := filepath.Join(fsPath, "b") brokenSymlink := filepath.Join(fsPath, "c") - os.Symlink("a", workingSymlink) - os.Symlink("non-existent", brokenSymlink) + err := os.Symlink("a", workingSymlink) + require.NoError(t, err) + err = os.Symlink("non-existent", brokenSymlink) + require.NoError(t, err) matches, err := Glob(workingSymlink) require.NoError(t, err) From d7f7a7c91d2c04d77fdc52ede9b5b98e2c1a183a Mon Sep 17 00:00:00 2001 From: "Mikhail f. Shiryaev" Date: Wed, 9 Feb 2022 17:28:56 +0100 Subject: [PATCH 3/4] test: fix assertion linting --- glob_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/glob_test.go b/glob_test.go index 53dbbd4..188fc3c 100644 --- a/glob_test.go +++ b/glob_test.go @@ -453,11 +453,11 @@ func TestGlob(t *testing.T) { // nolint:funlen t.Run("symlinks", func(t *testing.T) { t.Parallel() - testFS := testFs(t, []string{ - "./a/file", - }, nil).(testfs.FS) + var fsPath string + if testFS, ok := testFs(t, []string{"./a/file"}, nil).(testfs.FS); ok { + fsPath = testFS.Path() + } - fsPath := testFS.Path() workingSymlink := filepath.Join(fsPath, "b") brokenSymlink := filepath.Join(fsPath, "c") err := os.Symlink("a", workingSymlink) From cb8d871a59c6d4ebe6b5540d9ba742b8719b4c6f Mon Sep 17 00:00:00 2001 From: "Mikhail f. Shiryaev" Date: Wed, 9 Feb 2022 19:10:52 +0100 Subject: [PATCH 4/4] Ignore linter in shadowing error --- glob.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/glob.go b/glob.go index bcbcf6e..fee0751 100644 --- a/glob.go +++ b/glob.go @@ -126,7 +126,7 @@ func Glob(pattern string, opts ...OptFunc) ([]string, error) { // nolint:funlen, // Check if the file is valid symlink without following it // It works only for valid absolut or relative file paths, in other words, will fail for WithFs() option - if patternInfo, err := os.Lstat(pattern); err == nil { + if patternInfo, err := os.Lstat(pattern); err == nil { // nolint:govet if patternInfo.Mode()&os.ModeSymlink == os.ModeSymlink { return cleanFilepaths([]string{pattern}, options.prefix), nil }