From ac4a9434203a2e6df14ff100d7ca79438890232f Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Thu, 20 Apr 2023 08:44:23 +0300 Subject: [PATCH 1/3] feat: allow root break for mapfs --- pkg/mapfs/fs.go | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/pkg/mapfs/fs.go b/pkg/mapfs/fs.go index d075b02d2336..3522320d5705 100644 --- a/pkg/mapfs/fs.go +++ b/pkg/mapfs/fs.go @@ -28,11 +28,26 @@ var _ allFS = &FS{} // FS is an in-memory filesystem type FS struct { root *file + + // When the underlyingRoot has a value, it allows access to the local filesystem outside of this in-memory filesystem. + // The set path is used as the starting point when accessing the local filesystem. + // In other words, although mapfs.Open("../foo") would normally result in an error, if this option is enabled, + // it will be executed as os.Open(filepath.Join(underlyingRoot, "../foo")). + underlyingRoot string +} + +type Option func(*FS) + +// WithUnderlyingRoot returns an option to set the underlying root path for the in-memory filesystem. +func WithUnderlyingRoot(root string) Option { + return func(fsys *FS) { + fsys.underlyingRoot = root + } } // New creates a new filesystem -func New() *FS { - return &FS{ +func New(opts ...Option) *FS { + fsys := &FS{ root: &file{ stat: fileStat{ name: ".", @@ -43,6 +58,10 @@ func New() *FS { files: syncx.Map[string, *file]{}, }, } + for _, opt := range opts { + opt(fsys) + } + return fsys } // Filter removes the specified skippedFiles and returns a new FS @@ -90,6 +109,10 @@ func (m *FS) CopyFilesUnder(dir string) error { // Stat returns a FileInfo describing the file. func (m *FS) Stat(name string) (fs.FileInfo, error) { + if strings.HasPrefix(name, "../") && m.underlyingRoot != "" { + return os.Stat(filepath.Join(m.underlyingRoot, name)) + } + name = cleanPath(name) f, err := m.root.getFile(name) if err != nil { @@ -108,11 +131,17 @@ func (m *FS) Stat(name string) (fs.FileInfo, error) { // ReadDir reads the named directory // and returns a list of directory entries sorted by filename. func (m *FS) ReadDir(name string) ([]fs.DirEntry, error) { + if strings.HasPrefix(name, "../") && m.underlyingRoot != "" { + return os.ReadDir(filepath.Join(m.underlyingRoot, name)) + } return m.root.ReadDir(cleanPath(name)) } // Open opens the named file for reading. func (m *FS) Open(name string) (fs.File, error) { + if strings.HasPrefix(name, "../") && m.underlyingRoot != "" { + return os.Open(filepath.Join(m.underlyingRoot, name)) + } return m.root.Open(cleanPath(name)) } @@ -145,6 +174,10 @@ func (m *FS) MkdirAll(path string, perm fs.FileMode) error { // The caller is permitted to modify the returned byte slice. // This method should return a copy of the underlying data. func (m *FS) ReadFile(name string) ([]byte, error) { + if strings.HasPrefix(name, "../") && m.underlyingRoot != "" { + return os.ReadFile(filepath.Join(m.underlyingRoot, name)) + } + f, err := m.root.Open(cleanPath(name)) if err != nil { return nil, err From c5cc8f48e14c640e49bf3ee4b3915bd5696c1ff9 Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Thu, 20 Apr 2023 08:58:43 +0300 Subject: [PATCH 2/3] feat(fs): allow root break --- pkg/fanal/artifact/local/fs.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/fanal/artifact/local/fs.go b/pkg/fanal/artifact/local/fs.go index 3c461be10852..2fbaa8293970 100644 --- a/pkg/fanal/artifact/local/fs.go +++ b/pkg/fanal/artifact/local/fs.go @@ -240,7 +240,9 @@ func (a Artifact) buildFS(dir, filePath string, info os.FileInfo, files *syncx.M // Create fs.FS for each post-analyzer that wants to analyze the current file for _, at := range atypes { - mfs, _ := files.LoadOrStore(at, mapfs.New()) + // Since filesystem scanning may require access outside the specified path, (e.g. Terraform modules) + // it allows "../" access with "WithUnderlyingRoot". + mfs, _ := files.LoadOrStore(at, mapfs.New(mapfs.WithUnderlyingRoot(dir))) if d := filepath.Dir(filePath); d != "." { if err := mfs.MkdirAll(d, os.ModePerm); err != nil && !errors.Is(err, fs.ErrExist) { return xerrors.Errorf("mapfs mkdir error: %w", err) From 97144fce827878a0636f0be63b41e485e3124bd1 Mon Sep 17 00:00:00 2001 From: knqyf263 Date: Sun, 23 Apr 2023 19:27:16 +0300 Subject: [PATCH 3/3] feat: inherit underlying root in FilterFunc --- pkg/mapfs/fs.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/mapfs/fs.go b/pkg/mapfs/fs.go index 456ef4ccadd2..d92a3fb48318 100644 --- a/pkg/mapfs/fs.go +++ b/pkg/mapfs/fs.go @@ -76,7 +76,7 @@ func (m *FS) Filter(skippedFiles []string) (*FS, error) { } func (m *FS) FilterFunc(fn func(path string, d fs.DirEntry) (bool, error)) (*FS, error) { - newFS := New() + newFS := New(WithUnderlyingRoot(m.underlyingRoot)) err := fs.WalkDir(m, ".", func(path string, d fs.DirEntry, err error) error { if err != nil { return err