mirror of
https://github.com/golang/go
synced 2024-10-06 08:00:07 +00:00
io/fs: fix stack exhaustion in Glob
A limit is added to the number of path separators allowed by an input to Glob, to prevent stack exhaustion issues. Thanks to Juho Nurminen of Mattermost who reported a similar issue in path/filepath. Fixes CVE-2022-30630 Fixes golang/go#53415 Change-Id: I5a9d02591fed90cd3d52627f5945f1301e53465d Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1497588 Reviewed-by: Roland Shoemaker <bracewell@google.com> Reviewed-on: https://go-review.googlesource.com/c/go/+/417065 Run-TryBot: Michael Knyszek <mknyszek@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Heschi Kreinick <heschi@google.com>
This commit is contained in:
parent
6fa37e98ea
commit
fa2d41d0ca
|
@ -31,6 +31,16 @@ type GlobFS interface {
|
||||||
// Otherwise, Glob uses ReadDir to traverse the directory tree
|
// Otherwise, Glob uses ReadDir to traverse the directory tree
|
||||||
// and look for matches for the pattern.
|
// and look for matches for the pattern.
|
||||||
func Glob(fsys FS, pattern string) (matches []string, err error) {
|
func Glob(fsys FS, pattern string) (matches []string, err error) {
|
||||||
|
return globWithLimit(fsys, pattern, 0)
|
||||||
|
}
|
||||||
|
|
||||||
|
func globWithLimit(fsys FS, pattern string, depth int) (matches []string, err error) {
|
||||||
|
// This limit is added to prevent stack exhaustion issues. See
|
||||||
|
// CVE-2022-30630.
|
||||||
|
const pathSeparatorsLimit = 10000
|
||||||
|
if depth > pathSeparatorsLimit {
|
||||||
|
return nil, path.ErrBadPattern
|
||||||
|
}
|
||||||
if fsys, ok := fsys.(GlobFS); ok {
|
if fsys, ok := fsys.(GlobFS); ok {
|
||||||
return fsys.Glob(pattern)
|
return fsys.Glob(pattern)
|
||||||
}
|
}
|
||||||
|
@ -59,9 +69,9 @@ func Glob(fsys FS, pattern string) (matches []string, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var m []string
|
var m []string
|
||||||
m, err = Glob(fsys, dir)
|
m, err = globWithLimit(fsys, dir, depth+1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return nil, err
|
||||||
}
|
}
|
||||||
for _, d := range m {
|
for _, d := range m {
|
||||||
matches, err = glob(fsys, d, file, matches)
|
matches, err = glob(fsys, d, file, matches)
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
. "io/fs"
|
. "io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -55,6 +56,15 @@ func TestGlobError(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCVE202230630(t *testing.T) {
|
||||||
|
// Prior to CVE-2022-30630, a stack exhaustion would occur given a large
|
||||||
|
// number of separators. There is now a limit of 10,000.
|
||||||
|
_, err := Glob(os.DirFS("."), "/*"+strings.Repeat("/", 10001))
|
||||||
|
if err != path.ErrBadPattern {
|
||||||
|
t.Fatalf("Glob returned err=%v, want %v", err, path.ErrBadPattern)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// contains reports whether vector contains the string s.
|
// contains reports whether vector contains the string s.
|
||||||
func contains(vector []string, s string) bool {
|
func contains(vector []string, s string) bool {
|
||||||
for _, elem := range vector {
|
for _, elem := range vector {
|
||||||
|
|
Loading…
Reference in a new issue