1// Copyright 2020 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package fs_test 6 7import ( 8 . "io/fs" 9 "os" 10 "path" 11 "slices" 12 "strings" 13 "testing" 14) 15 16var globTests = []struct { 17 fs FS 18 pattern, result string 19}{ 20 {os.DirFS("."), "glob.go", "glob.go"}, 21 {os.DirFS("."), "gl?b.go", "glob.go"}, 22 {os.DirFS("."), `gl\ob.go`, "glob.go"}, 23 {os.DirFS("."), "*", "glob.go"}, 24 {os.DirFS(".."), "*/glob.go", "fs/glob.go"}, 25} 26 27func TestGlob(t *testing.T) { 28 for _, tt := range globTests { 29 matches, err := Glob(tt.fs, tt.pattern) 30 if err != nil { 31 t.Errorf("Glob error for %q: %s", tt.pattern, err) 32 continue 33 } 34 if !slices.Contains(matches, tt.result) { 35 t.Errorf("Glob(%#q) = %#v want %v", tt.pattern, matches, tt.result) 36 } 37 } 38 for _, pattern := range []string{"no_match", "../*/no_match", `\*`} { 39 matches, err := Glob(os.DirFS("."), pattern) 40 if err != nil { 41 t.Errorf("Glob error for %q: %s", pattern, err) 42 continue 43 } 44 if len(matches) != 0 { 45 t.Errorf("Glob(%#q) = %#v want []", pattern, matches) 46 } 47 } 48} 49 50func TestGlobError(t *testing.T) { 51 bad := []string{`[]`, `nonexist/[]`} 52 for _, pattern := range bad { 53 _, err := Glob(os.DirFS("."), pattern) 54 if err != path.ErrBadPattern { 55 t.Errorf("Glob(fs, %#q) returned err=%v, want path.ErrBadPattern", pattern, err) 56 } 57 } 58} 59 60func TestCVE202230630(t *testing.T) { 61 // Prior to CVE-2022-30630, a stack exhaustion would occur given a large 62 // number of separators. There is now a limit of 10,000. 63 _, err := Glob(os.DirFS("."), "/*"+strings.Repeat("/", 10001)) 64 if err != path.ErrBadPattern { 65 t.Fatalf("Glob returned err=%v, want %v", err, path.ErrBadPattern) 66 } 67} 68 69type globOnly struct{ GlobFS } 70 71func (globOnly) Open(name string) (File, error) { return nil, ErrNotExist } 72 73func TestGlobMethod(t *testing.T) { 74 check := func(desc string, names []string, err error) { 75 t.Helper() 76 if err != nil || len(names) != 1 || names[0] != "hello.txt" { 77 t.Errorf("Glob(%s) = %v, %v, want %v, nil", desc, names, err, []string{"hello.txt"}) 78 } 79 } 80 81 // Test that ReadDir uses the method when present. 82 names, err := Glob(globOnly{testFsys}, "*.txt") 83 check("readDirOnly", names, err) 84 85 // Test that ReadDir uses Open when the method is not present. 86 names, err = Glob(openOnly{testFsys}, "*.txt") 87 check("openOnly", names, err) 88} 89