don't actually truncate the line when parsing

We have the data, might as well interpret it (and return the new non-fatal
error). It's the line reader's job to prevent us from consuming excess data.
This commit is contained in:
Shivaram Lingamneni 2021-03-03 11:26:38 -05:00
parent 617723503e
commit 3fafe19ebb
2 changed files with 13 additions and 16 deletions

@ -43,7 +43,7 @@ var (
// length limit (typically 512 bytes). This error is non-fatal; if encountered
// when parsing a message, the message is parsed up to the length limit, and
// if encountered when serializing a message, the message is truncated to the limit.
ErrorBodyTooLong = errors.New("Line could not be processed because its body exceeded the length limit")
ErrorBodyTooLong = errors.New("Line body exceeded the specified length limit; outgoing messages will be truncated")
// ErrorTagsTooLong indicates that the message exceeded the maximum tag length
// (the specified response on the server side is 417 ERR_INPUTTOOLONG).
@ -162,14 +162,14 @@ func ParseLine(line string) (ircmsg IRCMessage, err error) {
// ParseLineStrict creates and returns an IRCMessage from the given IRC line,
// taking the maximum length into account and truncating the message as appropriate.
// If fromClient is true, it enforces the client limit on tag data length (4094 bytes),
// allowing the server to return ERR_INPUTTOOLONG as appropriate. If truncateLen is
// allowing the server to return ERR_INPUTTOOLONG as appropriate. If maxLenBody is
// nonzero, it is the length at which the non-tag portion of the message is truncated.
func ParseLineStrict(line string, fromClient bool, truncateLen int) (ircmsg IRCMessage, err error) {
func ParseLineStrict(line string, fromClient bool, maxLenBody int) (ircmsg IRCMessage, err error) {
maxTagDataLength := MaxlenTagData
if fromClient {
maxTagDataLength = MaxlenClientTagData
}
return parseLine(line, maxTagDataLength, truncateLen)
return parseLine(line, maxTagDataLength, maxLenBody)
}
// slice off any amount of ' ' from the front of the string
@ -180,17 +180,17 @@ func trimInitialSpaces(str string) string {
return str[i:]
}
func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IRCMessage, err error) {
func parseLine(line string, maxTagDataLength int, maxLenBody int) (ircmsg IRCMessage, err error) {
// remove either \n or \r\n from the end of the line:
line = strings.TrimSuffix(line, "\n")
line = strings.TrimSuffix(line, "\r")
// whether we removed them ourselves, or whether they were removed previously,
// they count against the line limit:
if truncateLen != 0 {
if truncateLen <= 2 {
if maxLenBody != 0 {
if maxLenBody <= 2 {
return ircmsg, ErrorLineIsEmpty
}
truncateLen -= 2
maxLenBody -= 2
}
// now validate for the 3 forbidden bytes:
if strings.IndexByte(line, '\x00') != -1 || strings.IndexByte(line, '\n') != -1 || strings.IndexByte(line, '\r') != -1 {
@ -220,9 +220,8 @@ func parseLine(line string, maxTagDataLength int, truncateLen int) (ircmsg IRCMe
}
// truncate if desired
if 0 < truncateLen && truncateLen < len(line) {
if maxLenBody != 0 && maxLenBody < len(line) {
err = ErrorBodyTooLong
line = line[:truncateLen]
}
// modern: "These message parts, and parameters themselves, are separated

@ -22,21 +22,19 @@ type testcodewithlen struct {
var decodelentests = []testcodewithlen{
{":dan-!d@localhost PRIVMSG dan #test :What a cool message\r\n", 22,
MakeMessage(nil, "dan-!d@localhost", "PR"), true},
MakeMessage(nil, "dan-!d@localhost", "PRIVMSG", "dan", "#test", "What a cool message"), true},
{"@time=12732;re TEST *\r\n", 512,
MakeMessage(map[string]string{"time": "12732", "re": ""}, "", "TEST", "*"), false},
{"@time=12732;re TEST *\r\n", 512,
MakeMessage(map[string]string{"time": "12732", "re": ""}, "", "TEST", "*"), false},
{":dan- TESTMSG\r\n", 2048,
MakeMessage(nil, "dan-", "TESTMSG"), false},
{":dan- TESTMSG dan \r\n", 14,
MakeMessage(nil, "dan-", "TESTMS"), true},
{"TESTMSG\r\n", 6,
MakeMessage(nil, "", "TEST"), true},
MakeMessage(nil, "", "TESTMSG"), true},
{"TESTMSG\r\n", 7,
MakeMessage(nil, "", "TESTM"), true},
MakeMessage(nil, "", "TESTMSG"), true},
{"TESTMSG\r\n", 8,
MakeMessage(nil, "", "TESTMS"), true},
MakeMessage(nil, "", "TESTMSG"), true},
{"TESTMSG\r\n", 9,
MakeMessage(nil, "", "TESTMSG"), false},
}