handlers: check array bounds before indexing

This commit is contained in:
John Soros 2015-11-29 04:28:05 +01:00
parent 1e190eb233
commit f0ae9bb509
3 changed files with 48 additions and 2 deletions

View File

@ -73,6 +73,9 @@ func (conn *Conn) h_433(line *Line) {
me := conn.Me() me := conn.Me()
neu := conn.cfg.NewNick(line.Args[1]) neu := conn.cfg.NewNick(line.Args[1])
conn.Nick(neu) conn.Nick(neu)
if !line.argslen(1) {
return
}
// if this is happening before we're properly connected (i.e. the nick // if this is happening before we're properly connected (i.e. the nick
// we sent in the initial NICK command is in use) we will not receive // we sent in the initial NICK command is in use) we will not receive
// a NICK message to confirm our change of nick, so ReNick here... // a NICK message to confirm our change of nick, so ReNick here...
@ -89,7 +92,7 @@ func (conn *Conn) h_433(line *Line) {
func (conn *Conn) h_CTCP(line *Line) { func (conn *Conn) h_CTCP(line *Line) {
if line.Args[0] == VERSION { if line.Args[0] == VERSION {
conn.CtcpReply(line.Nick, VERSION, conn.cfg.Version) conn.CtcpReply(line.Nick, VERSION, conn.cfg.Version)
} else if line.Args[0] == PING { } else if line.Args[0] == PING && line.argslen(2) {
conn.CtcpReply(line.Nick, PING, line.Args[2]) conn.CtcpReply(line.Nick, PING, line.Args[2])
} }
} }

View File

@ -3,6 +3,8 @@ package client
import ( import (
"strings" "strings"
"time" "time"
"runtime"
"github.com/fluffle/goirc/logging"
) )
// We parse an incoming line into this struct. Line.Cmd is used as the trigger // We parse an incoming line into this struct. Line.Cmd is used as the trigger
@ -156,3 +158,14 @@ func ParseLine(s string) *Line {
} }
return line return line
} }
func (line *Line) argslen(minlen int) bool {
pc, _, _, _ := runtime.Caller(1)
fn := runtime.FuncForPC(pc)
if len(line.Args) <= minlen {
logging.Warn("%s: too few arguments: %s", fn.Name(), strings.Join(line.Args, " "))
return false
}
return true
}

View File

@ -83,6 +83,9 @@ func (conn *Conn) h_PART(line *Line) {
// Handle KICKs from channels to maintain state // Handle KICKs from channels to maintain state
func (conn *Conn) h_KICK(line *Line) { func (conn *Conn) h_KICK(line *Line) {
if !line.argslen(1) {
return
}
// XXX: this won't handle autorejoining channels on KICK // XXX: this won't handle autorejoining channels on KICK
// it's trivial to do this in a seperate handler... // it's trivial to do this in a seperate handler...
conn.st.Dissociate(line.Args[0], line.Args[1]) conn.st.Dissociate(line.Args[0], line.Args[1])
@ -95,6 +98,9 @@ func (conn *Conn) h_QUIT(line *Line) {
// Handle MODE changes for channels we know about (and our nick personally) // Handle MODE changes for channels we know about (and our nick personally)
func (conn *Conn) h_MODE(line *Line) { func (conn *Conn) h_MODE(line *Line) {
if !line.argslen(1) {
return
}
if ch := conn.st.GetChannel(line.Args[0]); ch != nil { if ch := conn.st.GetChannel(line.Args[0]); ch != nil {
// channel modes first // channel modes first
conn.st.ChannelModes(line.Args[0], line.Args[1], line.Args[2:]...) conn.st.ChannelModes(line.Args[0], line.Args[1], line.Args[2:]...)
@ -114,6 +120,9 @@ func (conn *Conn) h_MODE(line *Line) {
// Handle TOPIC changes for channels // Handle TOPIC changes for channels
func (conn *Conn) h_TOPIC(line *Line) { func (conn *Conn) h_TOPIC(line *Line) {
if !line.argslen(1) {
return
}
if ch := conn.st.GetChannel(line.Args[0]); ch != nil { if ch := conn.st.GetChannel(line.Args[0]); ch != nil {
conn.st.Topic(line.Args[0], line.Args[1]) conn.st.Topic(line.Args[0], line.Args[1])
} else { } else {
@ -124,7 +133,10 @@ func (conn *Conn) h_TOPIC(line *Line) {
// Handle 311 whois reply // Handle 311 whois reply
func (conn *Conn) h_311(line *Line) { func (conn *Conn) h_311(line *Line) {
if nk := conn.st.GetNick(line.Args[1]); nk != nil && !conn.Me().Equals(nk) { if !line.argslen(5) {
return
}
if nk := conn.st.GetNick(line.Args[1]); (nk != nil) && !conn.Me().Equals(nk) {
conn.st.NickInfo(line.Args[1], line.Args[2], line.Args[3], line.Args[5]) conn.st.NickInfo(line.Args[1], line.Args[2], line.Args[3], line.Args[5])
} else { } else {
logging.Warn("irc.311(): received WHOIS info for unknown nick %s", logging.Warn("irc.311(): received WHOIS info for unknown nick %s",
@ -134,6 +146,9 @@ func (conn *Conn) h_311(line *Line) {
// Handle 324 mode reply // Handle 324 mode reply
func (conn *Conn) h_324(line *Line) { func (conn *Conn) h_324(line *Line) {
if !line.argslen(2) {
return
}
if ch := conn.st.GetChannel(line.Args[1]); ch != nil { if ch := conn.st.GetChannel(line.Args[1]); ch != nil {
conn.st.ChannelModes(line.Args[1], line.Args[2], line.Args[3:]...) conn.st.ChannelModes(line.Args[1], line.Args[2], line.Args[3:]...)
} else { } else {
@ -144,6 +159,9 @@ func (conn *Conn) h_324(line *Line) {
// Handle 332 topic reply on join to channel // Handle 332 topic reply on join to channel
func (conn *Conn) h_332(line *Line) { func (conn *Conn) h_332(line *Line) {
if !line.argslen(2) {
return
}
if ch := conn.st.GetChannel(line.Args[1]); ch != nil { if ch := conn.st.GetChannel(line.Args[1]); ch != nil {
conn.st.Topic(line.Args[1], line.Args[2]) conn.st.Topic(line.Args[1], line.Args[2])
} else { } else {
@ -154,6 +172,9 @@ func (conn *Conn) h_332(line *Line) {
// Handle 352 who reply // Handle 352 who reply
func (conn *Conn) h_352(line *Line) { func (conn *Conn) h_352(line *Line) {
if !line.argslen(5) {
return
}
nk := conn.st.GetNick(line.Args[5]) nk := conn.st.GetNick(line.Args[5])
if nk == nil { if nk == nil {
logging.Warn("irc.352(): received WHO reply for unknown nick %s", logging.Warn("irc.352(): received WHO reply for unknown nick %s",
@ -168,6 +189,9 @@ func (conn *Conn) h_352(line *Line) {
// last arg contains "<hop count> <real name>" // last arg contains "<hop count> <real name>"
a := strings.SplitN(line.Args[len(line.Args)-1], " ", 2) a := strings.SplitN(line.Args[len(line.Args)-1], " ", 2)
conn.st.NickInfo(nk.Nick, line.Args[2], line.Args[3], a[1]) conn.st.NickInfo(nk.Nick, line.Args[2], line.Args[3], a[1])
if !line.argslen(6) {
return
}
if idx := strings.Index(line.Args[6], "*"); idx != -1 { if idx := strings.Index(line.Args[6], "*"); idx != -1 {
conn.st.NickModes(nk.Nick, "+o") conn.st.NickModes(nk.Nick, "+o")
} }
@ -181,6 +205,9 @@ func (conn *Conn) h_352(line *Line) {
// Handle 353 names reply // Handle 353 names reply
func (conn *Conn) h_353(line *Line) { func (conn *Conn) h_353(line *Line) {
if !line.argslen(2) {
return
}
if ch := conn.st.GetChannel(line.Args[2]); ch != nil { if ch := conn.st.GetChannel(line.Args[2]); ch != nil {
nicks := strings.Split(line.Args[len(line.Args)-1], " ") nicks := strings.Split(line.Args[len(line.Args)-1], " ")
for _, nick := range nicks { for _, nick := range nicks {
@ -223,6 +250,9 @@ func (conn *Conn) h_353(line *Line) {
// Handle 671 whois reply (nick connected via SSL) // Handle 671 whois reply (nick connected via SSL)
func (conn *Conn) h_671(line *Line) { func (conn *Conn) h_671(line *Line) {
if !line.argslen(1) {
return
}
if nk := conn.st.GetNick(line.Args[1]); nk != nil { if nk := conn.st.GetNick(line.Args[1]); nk != nil {
conn.st.NickModes(nk.Nick, "+z") conn.st.NickModes(nk.Nick, "+z")
} else { } else {