Browse Source

lib/fs: Be even more strict about Windows names (ref #7008) (#7012)

Things like nul.whatever.txt are also not allowed.
Jakob Borg 5 years ago
parent
commit
e6b1f67ecf
2 changed files with 48 additions and 13 deletions
  1. 22 13
      lib/fs/util.go
  2. 26 0
      lib/fs/util_test.go

+ 22 - 13
lib/fs/util.go

@@ -44,13 +44,19 @@ func getHomeDir() (string, error) {
 	return os.UserHomeDir()
 }
 
-var windowsDisallowedCharacters = string([]rune{
-	'<', '>', ':', '"', '|', '?', '*',
-	0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
-	11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
-	21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
-	31,
-})
+var (
+	windowsDisallowedCharacters = string([]rune{
+		'<', '>', ':', '"', '|', '?', '*',
+		0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+		11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
+		21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+		31,
+	})
+	windowsDisallowedNames = []string{"CON", "PRN", "AUX", "NUL",
+		"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
+		"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
+	}
+)
 
 func WindowsInvalidFilename(name string) error {
 	// None of the path components should end in space or period, or be a
@@ -65,12 +71,15 @@ func WindowsInvalidFilename(name string) error {
 			// Names ending in space or period are not valid.
 			return errInvalidFilenameWindowsSpacePeriod
 		}
-		switch strings.ToUpper(part) {
-		case "CON", "PRN", "AUX", "NUL",
-			"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
-			"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9":
-			// These reserved names are not valid.
-			return errInvalidFilenameWindowsReservedName
+		upperCased := strings.ToUpper(part)
+		for _, disallowed := range windowsDisallowedNames {
+			if upperCased == disallowed {
+				return errInvalidFilenameWindowsReservedName
+			}
+			if strings.HasPrefix(upperCased, disallowed+".") {
+				// nul.txt.jpg is also disallowed
+				return errInvalidFilenameWindowsReservedName
+			}
 		}
 	}
 

+ 26 - 0
lib/fs/util_test.go

@@ -44,3 +44,29 @@ func TestCommonPrefix(t *testing.T) {
 	test(`Audrius`, `Audrius`, `Audrius`)
 	test(`.`, `.`, `.`)
 }
+
+func TestWindowsInvalidFilename(t *testing.T) {
+	cases := []struct {
+		name string
+		err  error
+	}{
+		{`asdf.txt`, nil},
+		{`nul`, errInvalidFilenameWindowsReservedName},
+		{`nul.txt`, errInvalidFilenameWindowsReservedName},
+		{`nul.jpg.txt`, errInvalidFilenameWindowsReservedName},
+		{`some.nul.jpg`, nil},
+		{`foo>bar.txt`, errInvalidFilenameWindowsReservedChar},
+		{`foo \bar.txt`, errInvalidFilenameWindowsSpacePeriod},
+		{`foo.\bar.txt`, errInvalidFilenameWindowsSpacePeriod},
+		{`foo.d\bar.txt`, nil},
+		{`foo.d\bar .txt`, nil},
+		{`foo.d\bar. txt`, nil},
+	}
+
+	for _, tc := range cases {
+		err := WindowsInvalidFilename(tc.name)
+		if err != tc.err {
+			t.Errorf("For %q, got %v, expected %v", tc.name, err, tc.err)
+		}
+	}
+}