Skip to content

Commit 4504880

Browse files
committed
osfs: Expand dot on BoundOS
Signed-off-by: Paulo Gomes <[email protected]>
1 parent b7d9906 commit 4504880

File tree

2 files changed

+80
-3
lines changed

2 files changed

+80
-3
lines changed

osfs/os_bound.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
package osfs
2121

2222
import (
23+
"errors"
2324
"fmt"
2425
"os"
2526
"path/filepath"
@@ -29,6 +30,11 @@ import (
2930
"github.com/go-git/go-billy/v5"
3031
)
3132

33+
var (
34+
ErrBaseDirCannotBeRemoved = errors.New("base dir cannot be removed")
35+
ErrBaseDirCannotBeRenamed = errors.New("base dir cannot be renamed")
36+
)
37+
3238
// BoundOS is a fs implementation based on the OS filesystem which is bound to
3339
// a base dir.
3440
// Prefer this fs implementation over ChrootOS.
@@ -54,6 +60,7 @@ func (fs *BoundOS) Create(filename string) (billy.File, error) {
5460
}
5561

5662
func (fs *BoundOS) OpenFile(filename string, flag int, perm os.FileMode) (billy.File, error) {
63+
filename = fs.expandDot(filename)
5764
fn, err := fs.abs(filename)
5865
if err != nil {
5966
return nil, err
@@ -62,6 +69,7 @@ func (fs *BoundOS) OpenFile(filename string, flag int, perm os.FileMode) (billy.
6269
}
6370

6471
func (fs *BoundOS) ReadDir(path string) ([]os.FileInfo, error) {
72+
path = fs.expandDot(path)
6573
dir, err := fs.abs(path)
6674
if err != nil {
6775
return nil, err
@@ -71,6 +79,12 @@ func (fs *BoundOS) ReadDir(path string) ([]os.FileInfo, error) {
7179
}
7280

7381
func (fs *BoundOS) Rename(from, to string) error {
82+
if from == "." || from == fs.baseDir {
83+
return ErrBaseDirCannotBeRenamed
84+
}
85+
86+
from = fs.expandDot(from)
87+
to = fs.expandDot(to)
7488
f, err := fs.abs(from)
7589
if err != nil {
7690
return err
@@ -89,6 +103,7 @@ func (fs *BoundOS) Rename(from, to string) error {
89103
}
90104

91105
func (fs *BoundOS) MkdirAll(path string, perm os.FileMode) error {
106+
path = fs.expandDot(path)
92107
dir, err := fs.abs(path)
93108
if err != nil {
94109
return err
@@ -97,10 +112,12 @@ func (fs *BoundOS) MkdirAll(path string, perm os.FileMode) error {
97112
}
98113

99114
func (fs *BoundOS) Open(filename string) (billy.File, error) {
115+
filename = fs.expandDot(filename)
100116
return fs.OpenFile(filename, os.O_RDONLY, 0)
101117
}
102118

103119
func (fs *BoundOS) Stat(filename string) (os.FileInfo, error) {
120+
filename = fs.expandDot(filename)
104121
filename, err := fs.abs(filename)
105122
if err != nil {
106123
return nil, err
@@ -109,6 +126,10 @@ func (fs *BoundOS) Stat(filename string) (os.FileInfo, error) {
109126
}
110127

111128
func (fs *BoundOS) Remove(filename string) error {
129+
if filename == "." || filename == fs.baseDir {
130+
return ErrBaseDirCannotBeRemoved
131+
}
132+
112133
fn, err := fs.abs(filename)
113134
if err != nil {
114135
return err
@@ -136,6 +157,11 @@ func (fs *BoundOS) Join(elem ...string) string {
136157
}
137158

138159
func (fs *BoundOS) RemoveAll(path string) error {
160+
if path == "." || path == fs.baseDir {
161+
return ErrBaseDirCannotBeRemoved
162+
}
163+
164+
path = fs.expandDot(path)
139165
dir, err := fs.abs(path)
140166
if err != nil {
141167
return err
@@ -144,6 +170,7 @@ func (fs *BoundOS) RemoveAll(path string) error {
144170
}
145171

146172
func (fs *BoundOS) Symlink(target, link string) error {
173+
link = fs.expandDot(link)
147174
ln, err := fs.abs(link)
148175
if err != nil {
149176
return err
@@ -155,7 +182,20 @@ func (fs *BoundOS) Symlink(target, link string) error {
155182
return os.Symlink(target, ln)
156183
}
157184

185+
func (fs *BoundOS) expandDot(p string) string {
186+
if p == "." {
187+
return fs.baseDir
188+
}
189+
for _, prefix := range []string{"./", ".\\"} {
190+
if strings.HasPrefix(p, prefix) {
191+
return filepath.Join(fs.baseDir, strings.TrimPrefix(p, prefix))
192+
}
193+
}
194+
return p
195+
}
196+
158197
func (fs *BoundOS) Lstat(filename string) (os.FileInfo, error) {
198+
filename = fs.expandDot(filename)
159199
filename = filepath.Clean(filename)
160200
if !filepath.IsAbs(filename) {
161201
filename = filepath.Join(fs.baseDir, filename)
@@ -167,6 +207,7 @@ func (fs *BoundOS) Lstat(filename string) (os.FileInfo, error) {
167207
}
168208

169209
func (fs *BoundOS) Readlink(link string) (string, error) {
210+
link = fs.expandDot(link)
170211
if !filepath.IsAbs(link) {
171212
link = filepath.Clean(filepath.Join(fs.baseDir, link))
172213
}
@@ -247,7 +288,7 @@ func (fs *BoundOS) insideBaseDir(filename string) (bool, error) {
247288
// that either filename or fs.baseDir may contain.
248289
func (fs *BoundOS) insideBaseDirEval(filename string) (bool, error) {
249290
// "/" contains all others.
250-
if fs.baseDir == "/" {
291+
if fs.baseDir == "/" || fs.baseDir == filename {
251292
return true, nil
252293
}
253294
dir, err := filepath.EvalSymlinks(filepath.Dir(filename))

osfs/os_bound_test.go

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ func TestOpen(t *testing.T) {
4747
},
4848
filename: "test-file",
4949
},
50+
{
51+
name: "file: dot rel same dir",
52+
before: func(dir string) billy.Filesystem {
53+
os.WriteFile(filepath.Join(dir, "test-file"), []byte("anything"), 0o600)
54+
return newBoundOS(dir, true)
55+
},
56+
filename: "./test-file",
57+
},
5058
{
5159
name: "file: rel path to above cwd",
5260
before: func(dir string) billy.Filesystem {
@@ -160,6 +168,11 @@ func Test_Symlink(t *testing.T) {
160168
link: "symlink",
161169
target: filepath.FromSlash("/etc/passwd"),
162170
},
171+
{
172+
name: "dot link to abs valid target",
173+
link: "./symlink",
174+
target: filepath.FromSlash("/etc/passwd"),
175+
},
163176
{
164177
name: "link to abs inexistent target",
165178
link: "symlink",
@@ -507,6 +520,14 @@ func TestLstat(t *testing.T) {
507520
},
508521
filename: "test-file",
509522
},
523+
{
524+
name: "file: dot rel",
525+
before: func(dir string) billy.Filesystem {
526+
os.WriteFile(filepath.Join(dir, "test-file"), []byte("anything"), 0o600)
527+
return newBoundOS(dir, true)
528+
},
529+
filename: "./test-file",
530+
},
510531
{
511532
name: "file: abs",
512533
before: func(dir string) billy.Filesystem {
@@ -610,6 +631,13 @@ func TestStat(t *testing.T) {
610631
},
611632
filename: "test-file",
612633
},
634+
{
635+
name: "rel dot dir",
636+
before: func(dir string) billy.Filesystem {
637+
return newBoundOS(dir, true)
638+
},
639+
filename: ".",
640+
},
613641
{
614642
name: "abs file",
615643
before: func(dir string) billy.Filesystem {
@@ -674,6 +702,14 @@ func TestRemove(t *testing.T) {
674702
filename: "inexistent",
675703
wantErr: notFoundError(),
676704
},
705+
{
706+
name: "same dot dir",
707+
before: func(dir string) billy.Filesystem {
708+
return newBoundOS(dir, true)
709+
},
710+
filename: ".",
711+
wantErr: "base dir cannot be removed",
712+
},
677713
{
678714
name: "same dir file",
679715
before: func(dir string) billy.Filesystem {
@@ -1105,10 +1141,10 @@ func TestReadDir(t *testing.T) {
11051141
g.Expect(dirs).To(gomega.BeNil())
11061142
}
11071143

1108-
func TestInsideBaseDirEval(t*testing.T) {
1144+
func TestInsideBaseDirEval(t *testing.T) {
11091145
g := gomega.NewWithT(t)
11101146
fs := BoundOS{baseDir: "/"}
1111-
b, err := fs.insideBaseDirEval("a")
1147+
b, err := fs.insideBaseDirEval("a")
11121148
g.Expect(b).To(gomega.BeTrue())
11131149
g.Expect(err).To(gomega.BeNil())
11141150
}

0 commit comments

Comments
 (0)