summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2014-09-09 20:02:03 -0400
committerJesse Luehrs <doy@tozt.net>2014-09-09 20:02:03 -0400
commited7945948ed9effdc26b31edfe27799a9f6abc0d (patch)
tree102d157cc88ce25e9f9384a9e7f968212635573a /src
parent1f00b773bb45e7c7a0c4acf3905aa2770e2f4470 (diff)
downloadrust-irc-ed7945948ed9effdc26b31edfe27799a9f6abc0d.tar.gz
rust-irc-ed7945948ed9effdc26b31edfe27799a9f6abc0d.zip
limit messages to 512 bytes
still need to avoid actually reading in bytes past 512 in an incoming message
Diffstat (limited to 'src')
-rw-r--r--src/client.rs3
-rw-r--r--src/constants.rs2
-rw-r--r--src/message.rs37
3 files changed, 29 insertions, 13 deletions
diff --git a/src/client.rs b/src/client.rs
index 3903fb7..c8f0d7b 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -142,6 +142,9 @@ impl Client {
// \n isn't valid inside a message, so this should be fine. if the \n
// we find isn't preceded by a \r, this will be caught by the message
// parser.
+ // XXX we should only be reading 512 bytes here, and throwing an error
+ // otherwise - or else we could end up reading an unbounded amount of
+ // data into memory
let buf = match self.conn().read_until(b'\n') {
Ok(b) => b,
Err(e) => return Err(IoError(e)),
diff --git a/src/constants.rs b/src/constants.rs
index ff5e399..b8b905e 100644
--- a/src/constants.rs
+++ b/src/constants.rs
@@ -337,7 +337,7 @@ pub static ERR_NOSERVICEHOST: u16 = 492;
pub static RPL_TOPICDATE: u16 = 333; // date the topic was set, in seconds since the epoch
pub static ERR_MSGFORBIDDEN: u16 = 505; // freenode blocking privmsg from unreged users
-pub static MAX_MESSAGE_LENGTH: i32 = 512;
+pub static MAX_MESSAGE_LENGTH: uint = 512;
#[test]
fn test_message_type () {
diff --git a/src/message.rs b/src/message.rs
index 5c1c76c..2115552 100644
--- a/src/message.rs
+++ b/src/message.rs
@@ -1,4 +1,4 @@
-use constants::MessageType;
+use constants::{MessageType, MAX_MESSAGE_LENGTH};
use std::io;
@@ -15,6 +15,10 @@ impl Message {
}
pub fn parse (msg: &str) -> Result<Message, &'static str> {
+ if msg.len() > MAX_MESSAGE_LENGTH {
+ return Err("message too long");
+ }
+
let message_parser = regex!(r"^(?::([^ ]+) )?([A-Z]+|[0-9]{3}) ([^\r\n\0]*)\r\n$");
match message_parser.captures(msg) {
Some(captures) => {
@@ -50,23 +54,32 @@ impl Message {
}
pub fn write_protocol_string<W: Writer> (&self, w: &mut W) -> io::IoResult<()> {
- match self.from {
- Some(ref f) => { try!(write!(w, ":{} ", f)) },
- None => {},
- }
+ let mut buf = [0u8, ..MAX_MESSAGE_LENGTH];
- try!(write!(w, "{}", self.message_type));
+ {
+ let mut bufw = io::BufWriter::new(buf);
- for param in self.params.iter() {
- if param.as_slice().contains_char(' ') {
- try!(write!(w, " :{}", param));
+ match self.from {
+ Some(ref f) => { try!(write!(bufw, ":{} ", f)) },
+ None => {},
}
- else {
- try!(write!(w, " {}", param));
+
+ try!(write!(bufw, "{}", self.message_type));
+
+ for param in self.params.iter() {
+ if param.as_slice().contains_char(' ') {
+ try!(write!(bufw, " :{}", param));
+ }
+ else {
+ try!(write!(bufw, " {}", param));
+ }
}
+
+ try!(write!(bufw, "\r\n"));
}
- try!(write!(w, "\r\n"));
+ let len = buf.iter().position(|&c| c == 0).unwrap_or(MAX_MESSAGE_LENGTH);
+ try!(w.write(buf.slice(0, len)));
try!(w.flush());
Ok(())