Make casemapping work over bytes instead of runes

Fixes a panic in partialCasemap when the input string was invalid UTF-8.
This commit is contained in:
Hubert Hirtz 2021-04-13 10:21:52 +02:00 committed by Simon Ser
parent c375c7d922
commit 70e5ed05b6

58
irc.go
View File

@ -429,57 +429,51 @@ func casemapNone(name string) string {
// CasemapASCII of name is the canonical representation of name according to the // CasemapASCII of name is the canonical representation of name according to the
// ascii casemapping. // ascii casemapping.
func casemapASCII(name string) string { func casemapASCII(name string) string {
var sb strings.Builder nameBytes := []byte(name)
sb.Grow(len(name)) for i, r := range nameBytes {
for _, r := range name {
if 'A' <= r && r <= 'Z' { if 'A' <= r && r <= 'Z' {
r += 'a' - 'A' nameBytes[i] = r + 'a' - 'A'
} }
sb.WriteRune(r)
} }
return sb.String() return string(nameBytes)
} }
// casemapRFC1459 of name is the canonical representation of name according to the // casemapRFC1459 of name is the canonical representation of name according to the
// rfc1459 casemapping. // rfc1459 casemapping.
func casemapRFC1459(name string) string { func casemapRFC1459(name string) string {
var sb strings.Builder nameBytes := []byte(name)
sb.Grow(len(name)) for i, r := range nameBytes {
for _, r := range name {
if 'A' <= r && r <= 'Z' { if 'A' <= r && r <= 'Z' {
r += 'a' - 'A' nameBytes[i] = r + 'a' - 'A'
} else if r == '{' { } else if r == '{' {
r = '[' nameBytes[i] = '['
} else if r == '}' { } else if r == '}' {
r = ']' nameBytes[i] = ']'
} else if r == '\\' { } else if r == '\\' {
r = '|' nameBytes[i] = '|'
} else if r == '~' { } else if r == '~' {
r = '^' nameBytes[i] = '^'
} }
sb.WriteRune(r)
} }
return sb.String() return string(nameBytes)
} }
// casemapRFC1459Strict of name is the canonical representation of name // casemapRFC1459Strict of name is the canonical representation of name
// according to the rfc1459-strict casemapping. // according to the rfc1459-strict casemapping.
func casemapRFC1459Strict(name string) string { func casemapRFC1459Strict(name string) string {
var sb strings.Builder nameBytes := []byte(name)
sb.Grow(len(name)) for i, r := range nameBytes {
for _, r := range name {
if 'A' <= r && r <= 'Z' { if 'A' <= r && r <= 'Z' {
r += 'a' - 'A' nameBytes[i] = r + 'a' - 'A'
} else if r == '{' { } else if r == '{' {
r = '[' nameBytes[i] = '['
} else if r == '}' { } else if r == '}' {
r = ']' nameBytes[i] = ']'
} else if r == '\\' { } else if r == '\\' {
r = '|' nameBytes[i] = '|'
} }
sb.WriteRune(r)
} }
return sb.String() return string(nameBytes)
} }
func parseCasemappingToken(tokenValue string) (casemap casemapping, ok bool) { func parseCasemappingToken(tokenValue string) (casemap casemapping, ok bool) {
@ -497,16 +491,14 @@ func parseCasemappingToken(tokenValue string) (casemap casemapping, ok bool) {
} }
func partialCasemap(higher casemapping, name string) string { func partialCasemap(higher casemapping, name string) string {
nameFullyCM := higher(name) nameFullyCM := []byte(higher(name))
var sb strings.Builder nameBytes := []byte(name)
sb.Grow(len(name)) for i, r := range nameBytes {
for i, r := range nameFullyCM { if !('A' <= r && r <= 'Z') && !('a' <= r && r <= 'z') {
if 'a' <= r && r <= 'z' { nameBytes[i] = nameFullyCM[i]
r = rune(name[i])
} }
sb.WriteRune(r)
} }
return sb.String() return string(nameBytes)
} }
type casemapMap struct { type casemapMap struct {