aboutsummaryrefslogtreecommitdiffstats
path: root/modules/storage
diff options
context:
space:
mode:
authorLunny Xiao <xiaolunwen@gmail.com>2022-03-14 23:18:27 +0800
committerGitHub <noreply@github.com>2022-03-14 16:18:27 +0100
commit49db87a035a28cd8eaa4abdd5832f952ca6449d9 (patch)
tree231676f5ca713844297cc16a52700fc50c8712fb /modules/storage
parent3ad6cf20695ea4e56e00427c6af76efc25e9b670 (diff)
downloadgitea-49db87a035a28cd8eaa4abdd5832f952ca6449d9.tar.gz
gitea-49db87a035a28cd8eaa4abdd5832f952ca6449d9.zip
Fix lfs bug (#19072)
* Fix lfs bug
Diffstat (limited to 'modules/storage')
-rw-r--r--modules/storage/local.go23
-rw-r--r--modules/storage/local_test.go45
2 files changed, 68 insertions, 0 deletions
diff --git a/modules/storage/local.go b/modules/storage/local.go
index 022e6186d4..8d9aa603d0 100644
--- a/modules/storage/local.go
+++ b/modules/storage/local.go
@@ -6,15 +6,20 @@ package storage
import (
"context"
+ "errors"
"io"
"net/url"
"os"
+ "path"
"path/filepath"
+ "strings"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/util"
)
+// ErrLocalPathNotSupported represents an error that path is not supported
+var ErrLocalPathNotSupported = errors.New("local path is not supported")
var _ ObjectStorage = &LocalStorage{}
// LocalStorageType is the type descriptor for local storage
@@ -59,11 +64,18 @@ func NewLocalStorage(ctx context.Context, cfg interface{}) (ObjectStorage, error
// Open a file
func (l *LocalStorage) Open(path string) (Object, error) {
+ if !isLocalPathValid(path) {
+ return nil, ErrLocalPathNotSupported
+ }
return os.Open(filepath.Join(l.dir, path))
}
// Save a file
func (l *LocalStorage) Save(path string, r io.Reader, size int64) (int64, error) {
+ if !isLocalPathValid(path) {
+ return 0, ErrLocalPathNotSupported
+ }
+
p := filepath.Join(l.dir, path)
if err := os.MkdirAll(filepath.Dir(p), os.ModePerm); err != nil {
return 0, err
@@ -107,8 +119,19 @@ func (l *LocalStorage) Stat(path string) (os.FileInfo, error) {
return os.Stat(filepath.Join(l.dir, path))
}
+func isLocalPathValid(p string) bool {
+ a := path.Clean(p)
+ if strings.HasPrefix(a, "../") || strings.HasPrefix(a, "..\\") {
+ return false
+ }
+ return a == p
+}
+
// Delete delete a file
func (l *LocalStorage) Delete(path string) error {
+ if !isLocalPathValid(path) {
+ return ErrLocalPathNotSupported
+ }
p := filepath.Join(l.dir, path)
return util.Remove(p)
}
diff --git a/modules/storage/local_test.go b/modules/storage/local_test.go
new file mode 100644
index 0000000000..8714f37f0d
--- /dev/null
+++ b/modules/storage/local_test.go
@@ -0,0 +1,45 @@
+// Copyright 2022 The Gitea Authors. All rights reserved.
+// Use of this source code is governed by a MIT-style
+// license that can be found in the LICENSE file.
+
+package storage
+
+import (
+ "testing"
+
+ "github.com/stretchr/testify/assert"
+)
+
+func TestLocalPathIsValid(t *testing.T) {
+ kases := []struct {
+ path string
+ valid bool
+ }{
+ {
+ "a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
+ true,
+ },
+ {
+ "../a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
+ false,
+ },
+ {
+ "a\\0\\a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
+ true,
+ },
+ {
+ "b/../a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
+ false,
+ },
+ {
+ "..\\a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a14",
+ false,
+ },
+ }
+
+ for _, k := range kases {
+ t.Run(k.path, func(t *testing.T) {
+ assert.EqualValues(t, k.valid, isLocalPathValid(k.path))
+ })
+ }
+}