diff --git a/protocol/src/errors.rs b/protocol/src/errors.rs index 8cf3f29..661ee70 100644 --- a/protocol/src/errors.rs +++ b/protocol/src/errors.rs @@ -55,6 +55,7 @@ error_chain! { foreign_links { Io(std::io::Error); FromUtf8(std::string::FromUtf8Error); + FromNulError(std::ffi::NulError); TryFromIntError(TryFromIntError); CharTryFromError(CharTryFromError); diff --git a/protocol/src/types/cstring.rs b/protocol/src/types/cstring.rs new file mode 100644 index 0000000..6216338 --- /dev/null +++ b/protocol/src/types/cstring.rs @@ -0,0 +1,59 @@ +use std::ffi::CString; +use std::io::prelude::{Read, Write}; +use {hint, util, Error, Parcel, Settings}; + +impl Parcel for CString { + const TYPE_NAME: &'static str = "CString"; + + fn read_field( + read: &mut dyn Read, + settings: &Settings, + _hints: &mut hint::Hints, + ) -> Result { + let mut result = Vec::new(); + // this logic is susceptible to DoS attacks by never providing + // a null character and will be fixed by + // https://github.com/dylanmckay/protocol/issues/14 + loop { + let c: u8 = Parcel::read(read, settings)?; + if c == 0x00 { + return Ok(CString::new(result)?); + } + result.push(c); + } + } + + fn write_field( + &self, + write: &mut dyn Write, + settings: &Settings, + _hints: &mut hint::Hints, + ) -> Result<(), Error> { + util::write_items(self.clone().into_bytes_with_nul().iter(), write, settings) + } +} + +#[cfg(test)] +mod test { + use std::ffi::CString; + use std::io::Cursor; + use {Parcel, Settings}; + + #[test] + fn can_read_cstring() { + let mut data = Cursor::new([0x41, 0x42, 0x43, 0]); + let read_back: CString = Parcel::read(&mut data, &Settings::default()).unwrap(); + assert_eq!(read_back, CString::new("ABC").unwrap()); + } + + #[test] + fn can_write_cstring() { + let mut buffer = Cursor::new(Vec::new()); + + CString::new("ABC") + .unwrap() + .write(&mut buffer, &Settings::default()) + .unwrap(); + assert_eq!(buffer.into_inner(), vec![0x41, 0x42, 0x43, 0]); + } +} diff --git a/protocol/src/types/mod.rs b/protocol/src/types/mod.rs index c5f786a..e8714b2 100644 --- a/protocol/src/types/mod.rs +++ b/protocol/src/types/mod.rs @@ -10,6 +10,7 @@ mod array; mod char; /// Definitions for the `std::collections` module. mod collections; +mod cstring; mod marker; mod numerics; mod option;