diff --git a/go.mod b/go.mod index f05d03aa..af9371f3 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815 github.com/ergochat/confusables v0.0.0-20201108231250-4ab98ab61fb1 github.com/ergochat/go-ident v0.0.0-20230911071154-8c30606d6881 - github.com/ergochat/irc-go v0.5.0-rc1 + github.com/ergochat/irc-go v0.5.0-rc2 github.com/go-sql-driver/mysql v1.7.0 github.com/go-test/deep v1.0.6 // indirect github.com/gofrs/flock v0.8.1 diff --git a/go.sum b/go.sum index d3f17af6..e1a1e55a 100644 --- a/go.sum +++ b/go.sum @@ -12,6 +12,8 @@ github.com/ergochat/go-ident v0.0.0-20230911071154-8c30606d6881 h1:+J5m88nvybxB5 github.com/ergochat/go-ident v0.0.0-20230911071154-8c30606d6881/go.mod h1:ASYJtQujNitna6cVHsNQTGrfWvMPJ5Sa2lZlmsH65uM= github.com/ergochat/irc-go v0.5.0-rc1 h1:kFoIHExoNFQ2CV+iShAVna/H4xrXQB4t4jK5Sep2j9k= github.com/ergochat/irc-go v0.5.0-rc1/go.mod h1:2vi7KNpIPWnReB5hmLpl92eMywQvuIeIIGdt/FQCph0= +github.com/ergochat/irc-go v0.5.0-rc2 h1:VuSQJF5K4hWvYSzGa4b8vgL6kzw8HF6LSOejE+RWpAo= +github.com/ergochat/irc-go v0.5.0-rc2/go.mod h1:2vi7KNpIPWnReB5hmLpl92eMywQvuIeIIGdt/FQCph0= github.com/ergochat/scram v1.0.2-ergo1 h1:2bYXiRFQH636pT0msOG39fmEYl4Eq+OuutcyDsCix/g= github.com/ergochat/scram v1.0.2-ergo1/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/ergochat/websocket v1.4.2-oragono1 h1:plMUunFBM6UoSCIYCKKclTdy/TkkHfUslhOfJQzfueM= diff --git a/vendor/github.com/ergochat/irc-go/ircmsg/message.go b/vendor/github.com/ergochat/irc-go/ircmsg/message.go index 7a7e1305..ae27c37b 100644 --- a/vendor/github.com/ergochat/irc-go/ircmsg/message.go +++ b/vendor/github.com/ergochat/irc-go/ircmsg/message.go @@ -196,6 +196,15 @@ func trimInitialSpaces(str string) string { return str[i:] } +func isASCII(str string) bool { + for i := 0; i < len(str); i++ { + if str[i] > 127 { + return false + } + } + return true +} + func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg Message, err error) { // remove either \n or \r\n from the end of the line: line = strings.TrimSuffix(line, "\n") @@ -265,11 +274,16 @@ func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg Messa commandEnd = len(line) paramStart = len(line) } - // normalize command to uppercase: - ircmsg.Command = strings.ToUpper(line[:commandEnd]) - if len(ircmsg.Command) == 0 { + baseCommand := line[:commandEnd] + if len(baseCommand) == 0 { return ircmsg, ErrorLineIsEmpty } + // technically this must be either letters or a 3-digit numeric: + if !isASCII(baseCommand) { + return ircmsg, ErrorLineContainsBadChar + } + // normalize command to uppercase: + ircmsg.Command = strings.ToUpper(baseCommand) line = line[paramStart:] for { diff --git a/vendor/github.com/ergochat/irc-go/ircutils/sasl.go b/vendor/github.com/ergochat/irc-go/ircutils/sasl.go index a4c612c6..31d3d0de 100644 --- a/vendor/github.com/ergochat/irc-go/ircutils/sasl.go +++ b/vendor/github.com/ergochat/irc-go/ircutils/sasl.go @@ -3,7 +3,6 @@ package ircutils import ( "encoding/base64" "errors" - "strings" ) var ( @@ -25,6 +24,7 @@ func EncodeSASLResponse(raw []byte) (result []string) { } response := base64.StdEncoding.EncodeToString(raw) + result = make([]string, 0, (len(response)/400)+1) lastLen := 0 for len(response) > 0 { // TODO once we require go 1.21, this can be: lastLen = min(len(response), 400) @@ -48,11 +48,11 @@ func EncodeSASLResponse(raw []byte) (result []string) { // Do not copy a SASLBuffer after first use. type SASLBuffer struct { maxLength int - buffer strings.Builder + buf []byte } // NewSASLBuffer returns a new SASLBuffer. maxLength is the maximum amount of -// base64'ed data to buffer (0 for no limit). +// data to buffer (0 for no limit). func NewSASLBuffer(maxLength int) *SASLBuffer { result := new(SASLBuffer) result.Initialize(maxLength) @@ -69,37 +69,43 @@ func (b *SASLBuffer) Initialize(maxLength int) { // response along with any decoding or protocol errors detected. func (b *SASLBuffer) Add(value string) (done bool, output []byte, err error) { if value == "+" { - output, err = b.getAndReset() - return true, output, err + // total size is a multiple of 400 (possibly 0) + output = b.buf + b.Clear() + return true, output, nil } if len(value) > 400 { - b.buffer.Reset() + b.Clear() return true, nil, ErrSASLTooLong } - if b.maxLength != 0 && (b.buffer.Len()+len(value)) > b.maxLength { - b.buffer.Reset() + curLen := len(b.buf) + chunkDecodedLen := base64.StdEncoding.DecodedLen(len(value)) + if b.maxLength != 0 && (curLen+chunkDecodedLen) > b.maxLength { + b.Clear() return true, nil, ErrSASLLimitExceeded } - b.buffer.WriteString(value) + // "append-make pattern" as in the bytes.Buffer implementation: + b.buf = append(b.buf, make([]byte, chunkDecodedLen)...) + n, err := base64.StdEncoding.Decode(b.buf[curLen:], []byte(value)) + b.buf = b.buf[0 : curLen+n] + if err != nil { + b.Clear() + return true, nil, err + } if len(value) < 400 { - output, err = b.getAndReset() - return true, output, err + output = b.buf + b.Clear() + return true, output, nil } else { - // 400 bytes, wait for continuation line or + return false, nil, nil } } // Clear resets the buffer state. func (b *SASLBuffer) Clear() { - b.buffer.Reset() -} - -func (b *SASLBuffer) getAndReset() (output []byte, err error) { - output, err = base64.StdEncoding.DecodeString(b.buffer.String()) - b.buffer.Reset() - return + // we can't reuse this buffer in general since we may have returned it + b.buf = nil } diff --git a/vendor/modules.txt b/vendor/modules.txt index e79f3026..948ba994 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -16,7 +16,7 @@ github.com/ergochat/confusables # github.com/ergochat/go-ident v0.0.0-20230911071154-8c30606d6881 ## explicit; go 1.18 github.com/ergochat/go-ident -# github.com/ergochat/irc-go v0.5.0-rc1 +# github.com/ergochat/irc-go v0.5.0-rc2 ## explicit; go 1.15 github.com/ergochat/irc-go/ircfmt github.com/ergochat/irc-go/ircmsg