Note that due to the default stack size limitations on Solaris, tests were removed from this patch as they won't pass by default. The fix was manually verified outside of the main test suite. From 315e80d293b684ac2902819e58f618f1b5a14d49 Mon Sep 17 00:00:00 2001 From: Julie Qiu Date: Thu, 23 Jun 2022 23:17:53 +0000 Subject: [PATCH] [release-branch.go1.18] 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 #53720 Updates #53415 Fixes CVE-2022-30630 Change-Id: I5a9d02591fed90cd3d52627f5945f1301e53465d Reviewed-on: https://team-review.git.corp.google.com/c/golang/go-private/+/1497588 Reviewed-by: Roland Shoemaker (cherry picked from commit fdccc5d7bd0f276d0a8de3a818ca844f0bed5d97) Reviewed-on: https://go-review.googlesource.com/c/go/+/417058 Run-TryBot: Michael Knyszek TryBot-Result: Gopher Robot Reviewed-by: Heschi Kreinick --- src/io/fs/glob.go | 14 ++++++++++++-- src/io/fs/glob_test.go | 10 ++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/src/io/fs/glob.go b/src/io/fs/glob.go index 45d9cb61b9632..0e529cd05d139 100644 --- a/libgo/go/io/fs/glob.go +++ b/libgo/go/io/fs/glob.go @@ -31,6 +31,16 @@ type GlobFS interface { // Otherwise, Glob uses ReadDir to traverse the directory tree // and look for matches for the pattern. 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 { return fsys.Glob(pattern) } @@ -59,9 +69,9 @@ func Glob(fsys FS, pattern string) (matches []string, err error) { } var m []string - m, err = Glob(fsys, dir) + m, err = globWithLimit(fsys, dir, depth+1) if err != nil { - return + return nil, err } for _, d := range m { matches, err = glob(fsys, d, file, matches)