From 4391b1ba5aaa2348176a9eac0e164721ee0a761a Mon Sep 17 00:00:00 2001 From: Shivaram Lingamneni Date: Sun, 22 Dec 2019 09:57:49 -0500 Subject: [PATCH] restrict ASCII mode to printable characters only --- irc/strings.go | 10 ++++++---- irc/strings_test.go | 48 +++++++++++++++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 16 deletions(-) diff --git a/irc/strings.go b/irc/strings.go index 3f9b82c4..32f3f952 100644 --- a/irc/strings.go +++ b/irc/strings.go @@ -9,7 +9,6 @@ import ( "fmt" "regexp" "strings" - "unicode" "github.com/oragono/confusables" "golang.org/x/text/cases" @@ -262,15 +261,18 @@ func CanonicalizeMaskWildcard(userhost string) (expanded string, err error) { } func foldASCII(str string) (result string, err error) { - if !IsPureASCII(str) { + if !IsPrintableASCII(str) { return "", errInvalidCharacter } return strings.ToLower(str), nil } -func IsPureASCII(str string) bool { +func IsPrintableASCII(str string) bool { for i := 0; i < len(str); i++ { - if unicode.MaxASCII < str[i] { + // allow space here because it's technically printable; + // it will be disallowed later by CasefoldName/CasefoldChannel + chr := str[i] + if chr < ' ' || chr > '~' { return false } } diff --git a/irc/strings_test.go b/irc/strings_test.go index 6780186f..9bb487f5 100644 --- a/irc/strings_test.go +++ b/irc/strings_test.go @@ -217,20 +217,24 @@ func TestCanonicalizeMaskWildcard(t *testing.T) { tester("*SHIVARAM*", "*shivaram*!*@*", nil) } +func validFoldTester(first, second string, equal bool, folder func(string) (string, error), t *testing.T) { + firstFolded, err := folder(first) + if err != nil { + panic(err) + } + secondFolded, err := folder(second) + if err != nil { + panic(err) + } + foundEqual := firstFolded == secondFolded + if foundEqual != equal { + t.Errorf("%s and %s: expected equality %t, but got %t", first, second, equal, foundEqual) + } +} + func TestFoldPermissive(t *testing.T) { tester := func(first, second string, equal bool) { - firstFolded, err := foldPermissive(first) - if err != nil { - panic(err) - } - secondFolded, err := foldPermissive(second) - if err != nil { - panic(err) - } - foundEqual := firstFolded == secondFolded - if foundEqual != equal { - t.Errorf("%s and %s: expected equality %t, but got %t", first, second, equal, foundEqual) - } + validFoldTester(first, second, equal, foldPermissive, t) } tester("SHIVARAM", "shivaram", true) tester("shIvaram", "shivaraM", true) @@ -250,3 +254,23 @@ func TestFoldPermissiveInvalid(t *testing.T) { t.Errorf("the null byte should be invalid in identifiers") } } + +func TestFoldASCII(t *testing.T) { + tester := func(first, second string, equal bool) { + validFoldTester(first, second, equal, foldASCII, t) + } + tester("shivaram", "SHIVARAM", true) + tester("X|Y", "x|y", true) + tester("a != b", "A != B", true) +} + +func TestFoldASCIIInvalid(t *testing.T) { + _, err := foldASCII("\x01") + if err == nil { + t.Errorf("control characters should be invalid in identifiers") + } + _, err = foldASCII("\x7F") + if err == nil { + t.Errorf("control characters should be invalid in identifiers") + } +}