From f3a5c0124a370a602752a91578330318f9fd8d15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Sun, 30 Nov 2014 18:26:25 -0800 Subject: [PATCH 1/2] Fix handling long Reason Phrase rfc2616 does not specify the maximum length of *Reason Phrase* so it's a good practice to handle even unreasonably long input. 16 char. buffer is not enough to correctly handle even the common `304 Moved Permanently`. Increase buffer size to more realistic 32. Also, up to 128 more characters will be read and ignored, providing even greater versatility without increasing memory usage. Issue #163 --- src/http.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/http.rs b/src/http.rs index 30313b40..57029f4c 100644 --- a/src/http.rs +++ b/src/http.rs @@ -609,11 +609,11 @@ pub fn read_status(stream: &mut R) -> HttpResult { _ => return Err(HttpStatusError) } - let mut buf = [b' ', ..16]; + let mut buf = [b' ', ..32]; { let mut bufwrt = BufWriter::new(&mut buf); - loop { + 'read: loop { match try!(stream.read_byte()) { CR => match try!(stream.read_byte()) { LF => break, @@ -622,8 +622,16 @@ pub fn read_status(stream: &mut R) -> HttpResult { b => match bufwrt.write_u8(b) { Ok(_) => (), Err(_) => { - // what sort of reason phrase is this long? - return Err(HttpStatusError); + for _ in range(0u, 128) { + match try!(stream.read_byte()) { + CR => match try!(stream.read_byte()) { + LF => break 'read, + _ => return Err(HttpStatusError) + }, + _ => { /* ignore */ } + } + } + return Err(HttpStatusError) } } } From f5a7d7cfa13a3a8f0b64cb2fa57cc20ad02e3673 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dawid=20Ci=C4=99=C5=BCarkiewicz?= Date: Sun, 30 Nov 2014 18:35:21 -0800 Subject: [PATCH 2/2] Tests for "Fix handling long Reason Phrase" Issue #163 --- src/http.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/http.rs b/src/http.rs index 57029f4c..be4ab35a 100644 --- a/src/http.rs +++ b/src/http.rs @@ -742,9 +742,22 @@ mod tests { assert_eq!(read_status(&mut mem(s)), result); } + fn read_ignore_string(s: &str, result: HttpResult) { + match (read_status(&mut mem(s)), result) { + (Ok(RawStatus(ref c1, _)), Ok(RawStatus(ref c2, _))) => { + assert_eq!(c1, c2); + }, + (r1, r2) => assert_eq!(r1, r2) + } + } + read("200 OK\r\n", Ok(RawStatus(200, Borrowed("OK")))); read("404 Not Found\r\n", Ok(RawStatus(404, Borrowed("Not Found")))); read("200 crazy pants\r\n", Ok(RawStatus(200, Owned("crazy pants".to_string())))); + read("301 Moved Permanently\r\n", Ok(RawStatus(301, Owned("Moved Permanently".to_string())))); + read_ignore_string("301 Unreasonably long header that should not happen, \ + but some men just want to watch the world burn\r\n", + Ok(RawStatus(301, Owned("Ignored".to_string())))); } #[test]