aboutsummaryrefslogtreecommitdiffstats
path: root/modules
diff options
context:
space:
mode:
author6543 <6543@obermui.de>2022-03-14 15:59:54 +0100
committerGitHub <noreply@github.com>2022-03-14 15:59:54 +0100
commit99861e3e067ae5bd80ce6b647cf9ace08556725b (patch)
tree8aac48d976a71a2e288cb592c5aa527db50cc1c3 /modules
parent66b8a43e5f9bd82f0daa3e7cbcab859457c8064f (diff)
downloadgitea-99861e3e067ae5bd80ce6b647cf9ace08556725b.tar.gz
gitea-99861e3e067ae5bd80ce6b647cf9ace08556725b.zip
Fix lfs bug (#19072) (#19080)
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'modules')
-rw-r--r--modules/storage/local.go27
-rw-r--r--modules/storage/local_test.go45
2 files changed, 69 insertions, 3 deletions
diff --git a/modules/storage/local.go b/modules/storage/local.go
index 54e0d0563d..8d9aa603d0 100644
--- a/modules/storage/local.go
+++ b/modules/storage/local.go
@@ -6,18 +6,21 @@ 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"
)
-var (
- _ ObjectStorage = &LocalStorage{}
-)
+// 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
const LocalStorageType Type = "local"
@@ -61,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
@@ -109,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))
+ })
+ }
+}