Source file src/io/fs/glob_test.go

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

View as plain text