From f1cf9064105bedcfce861aa4c564d6d5749b09e6 Mon Sep 17 00:00:00 2001
From: Covertness <wuyingfengsui@gmail.com>
Date: Thu, 20 Aug 2015 22:07:32 +0800
Subject: [PATCH] add test case

---
 Cargo.toml    |  5 ++++-
 src/client.rs | 22 ++++++++++++++++++++++
 src/lib.rs    |  1 +
 src/packet.rs | 33 +++++++++++++++++++++++++++++++++
 4 files changed, 60 insertions(+), 1 deletion(-)

diff --git a/Cargo.toml b/Cargo.toml
index 56ab3c4..af42945 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,4 +16,7 @@ mio = "0.3.7"
 threadpool = "0.1"
 url = "0.2.36"
 num = "0.1"
-rand = "0.3"
\ No newline at end of file
+rand = "0.3"
+
+[dev-dependencies]
+quickcheck = "*"
\ No newline at end of file
diff --git a/src/client.rs b/src/client.rs
index d92077c..13ec0fb 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -138,4 +138,26 @@ impl CoAPClient {
 			_ => SchemeType::NonRelative,
 		}
 	}
+}
+
+
+#[cfg(test)]
+mod test {
+	use super::*;
+	use packet::{Packet, PacketType};
+
+	#[test]
+	fn test_request_error_url() {
+		assert!(CoAPClient::request("http://127.0.0.1").is_err());
+		assert!(CoAPClient::request("coap://127.0.0.").is_err());
+		assert!(CoAPClient::request("127.0.0.1").is_err());
+	}
+
+	#[test]
+	fn test_reply_error() {
+		let client = CoAPClient::new("127.0.0.1:5683").unwrap();
+		let mut packet = Packet::new();
+		packet.header.set_type(PacketType::Acknowledgement);
+		assert!(client.reply(&packet, b"Test".to_vec()).is_err());
+	}
 }
\ No newline at end of file
diff --git a/src/lib.rs b/src/lib.rs
index 664ace2..2eaa9c7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -71,6 +71,7 @@ extern crate threadpool;
 extern crate url;
 extern crate num;
 extern crate rand;
+#[cfg(test)] extern crate quickcheck;
 
 pub use server::CoAPServer;
 pub use client::CoAPClient;
diff --git a/src/packet.rs b/src/packet.rs
index 691e95f..878c1a1 100644
--- a/src/packet.rs
+++ b/src/packet.rs
@@ -229,9 +229,16 @@ impl Packet {
 						idx += 1;
 
 						if delta == 13 {
+							if idx >= buf.len() {
+								return Err(ParseError::InvalidOptionLength);
+							}
 							delta = buf[idx] as usize + 13;
 							idx += 1;
 						} else if delta == 14 {
+							if idx + 1 >= buf.len() {
+								return Err(ParseError::InvalidOptionLength);
+							}
+
 							delta = (u16::from_be(u8_to_unsigned_be!(buf, idx, idx + 1, u16)) + 269) as usize;
 							idx += 2;
 						} else if delta == 15 {
@@ -239,9 +246,17 @@ impl Packet {
 						}
 
 						if length == 13 {
+							if idx >= buf.len() {
+								return Err(ParseError::InvalidOptionLength);
+							}
+
 							length = buf[idx] as usize + 13;
 							idx += 1;
 						} else if length == 14 {
+							if idx + 1 >= buf.len() {
+								return Err(ParseError::InvalidOptionLength);
+							}
+
 							length = (u16::from_be(u8_to_unsigned_be!(buf, idx, idx + 1, u16)) + 269) as usize;
 							idx += 2;
 						} else if length == 15 {
@@ -251,6 +266,9 @@ impl Packet {
 						options_number += delta;
 
 						let end = idx + length;
+						if end > buf.len() {
+							return Err(ParseError::InvalidOptionLength);
+						}
 						let options_value = buf[idx..end].to_vec();
 
 						if options.contains_key(&options_number) {
@@ -474,4 +492,19 @@ mod test {
 		packet.payload = "Hello".as_bytes().to_vec();
 		assert_eq!(packet.to_bytes().unwrap(), vec!(0x64, 0x45, 0x13, 0xFD, 0xD0, 0xE2, 0x4D, 0xAC, 0xFF, 0x48, 0x65, 0x6C, 0x6C, 0x6F));
 	}
+
+	#[test]
+	fn test_malicious_packet() {
+		use quickcheck::{QuickCheck, TestResult};
+
+		fn run(x: Vec<u8>) -> TestResult {
+			match Packet::from_bytes(&x[..]) {
+				Ok(packet) => {
+					TestResult::from_bool(packet.get_token().len() == packet.header.get_token_length() as usize)
+				},
+				Err(_) => TestResult::passed()
+			}
+		}
+		QuickCheck::new().tests(10000).quickcheck(run as fn(Vec<u8>) -> TestResult)
+	}
 }
\ No newline at end of file
-- 
GitLab