mirror of https://git.sr.ht/~stygianentity/bincode
177 invalid encodings (#212)
* split out invalid encoding errors * detail breaking changes
This commit is contained in:
parent
45e70e297e
commit
c8f02e30aa
|
|
@ -3,6 +3,7 @@ name = "bincode"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
authors = ["Ty Overby <ty@pre-alpha.com>", "Francesco Mazzoli <f@mazzo.li>", "David Tolnay <dtolnay@gmail.com>", "Daniel Griffen"]
|
authors = ["Ty Overby <ty@pre-alpha.com>", "Francesco Mazzoli <f@mazzo.li>", "David Tolnay <dtolnay@gmail.com>", "Daniel Griffen"]
|
||||||
|
|
||||||
|
# Adding ErrorKind::Invalid*Encoding is a breaking change
|
||||||
# Adding ErrorKind::DeserializeAnyNotSupported is a breaking change
|
# Adding ErrorKind::DeserializeAnyNotSupported is a breaking change
|
||||||
publish = false
|
publish = false
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -56,11 +56,9 @@ impl<'de, R: BincodeRead<'de>, E: ByteOrder, S: SizeLimit> Deserializer<R, S, E>
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_string(&mut self) -> Result<String> {
|
fn read_string(&mut self) -> Result<String> {
|
||||||
String::from_utf8(try!(self.read_vec())).map_err(|err|
|
let vec = self.read_vec()?;
|
||||||
ErrorKind::InvalidEncoding{
|
String::from_utf8(vec).map_err(|e|
|
||||||
desc: "error while decoding utf8 string",
|
ErrorKind::InvalidUtf8Encoding(e.utf8_error()).into())
|
||||||
detail: Some(format!("Deserialize error: {}", err))
|
|
||||||
}.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -96,10 +94,7 @@ where R: BincodeRead<'de>, S: SizeLimit, E: ByteOrder {
|
||||||
1 => visitor.visit_bool(true),
|
1 => visitor.visit_bool(true),
|
||||||
0 => visitor.visit_bool(false),
|
0 => visitor.visit_bool(false),
|
||||||
value => {
|
value => {
|
||||||
Err(ErrorKind::InvalidEncoding{
|
Err(ErrorKind::InvalidBoolEncoding(value).into())
|
||||||
desc: "invalid u8 when decoding bool",
|
|
||||||
detail: Some(format!("Expected 0 or 1, got {}", value))
|
|
||||||
}.into())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -142,10 +137,7 @@ where R: BincodeRead<'de>, S: SizeLimit, E: ByteOrder {
|
||||||
use std::str;
|
use std::str;
|
||||||
|
|
||||||
let error = || {
|
let error = || {
|
||||||
ErrorKind::InvalidEncoding{
|
ErrorKind::InvalidCharEncoding.into()
|
||||||
desc: "invalid char encoding",
|
|
||||||
detail: None,
|
|
||||||
}.into()
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut buf = [0u8; 4];
|
let mut buf = [0u8; 4];
|
||||||
|
|
@ -255,10 +247,7 @@ where R: BincodeRead<'de>, S: SizeLimit, E: ByteOrder {
|
||||||
match value {
|
match value {
|
||||||
0 => visitor.visit_none(),
|
0 => visitor.visit_none(),
|
||||||
1 => visitor.visit_some(&mut *self),
|
1 => visitor.visit_some(&mut *self),
|
||||||
_ => Err(ErrorKind::InvalidEncoding{
|
v => Err(ErrorKind::InvalidTagEncoding(v as usize).into())
|
||||||
desc: "invalid tag when decoding Option",
|
|
||||||
detail: Some(format!("Expected 0 or 1, got {}", value))
|
|
||||||
}.into()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,10 +81,7 @@ impl <'storage> BincodeRead<'storage> for SliceReader<'storage> {
|
||||||
|
|
||||||
let string = match ::std::str::from_utf8(&self.slice[..length]) {
|
let string = match ::std::str::from_utf8(&self.slice[..length]) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(_) => return Err(Box::new(ErrorKind::InvalidEncoding {
|
Err(e) => return Err(ErrorKind::InvalidUtf8Encoding(e).into()),
|
||||||
desc: "string was not valid utf8",
|
|
||||||
detail: None,
|
|
||||||
})),
|
|
||||||
};
|
};
|
||||||
let r = visitor.visit_borrowed_str(string);
|
let r = visitor.visit_borrowed_str(string);
|
||||||
self.slice = &self.slice[length..];
|
self.slice = &self.slice[length..];
|
||||||
|
|
@ -133,10 +130,7 @@ impl <R> BincodeRead<'static> for IoReader<R> where R: io::Read {
|
||||||
|
|
||||||
let string = match ::std::str::from_utf8(&self.temp_buffer[..length]) {
|
let string = match ::std::str::from_utf8(&self.temp_buffer[..length]) {
|
||||||
Ok(s) => s,
|
Ok(s) => s,
|
||||||
Err(_) => return Err(Box::new(::ErrorKind::InvalidEncoding {
|
Err(e) => return Err(::ErrorKind::InvalidUtf8Encoding(e).into()),
|
||||||
desc: "string was not valid utf8",
|
|
||||||
detail: None,
|
|
||||||
})),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let r = visitor.visit_str(string);
|
let r = visitor.visit_str(string);
|
||||||
|
|
|
||||||
|
|
@ -4,8 +4,10 @@
|
||||||
|
|
||||||
use std::io::{self, Write, Read};
|
use std::io::{self, Write, Read};
|
||||||
use std::{error, fmt, result};
|
use std::{error, fmt, result};
|
||||||
|
use std::str::Utf8Error;
|
||||||
use ::{CountSize, SizeLimit};
|
use ::{CountSize, SizeLimit};
|
||||||
use byteorder::{ByteOrder};
|
use byteorder::{ByteOrder};
|
||||||
|
use std::error::Error as StdError;
|
||||||
|
|
||||||
pub use super::de::{
|
pub use super::de::{
|
||||||
Deserializer,
|
Deserializer,
|
||||||
|
|
@ -31,16 +33,16 @@ pub enum ErrorKind {
|
||||||
/// If the error stems from the reader/writer that is being used
|
/// If the error stems from the reader/writer that is being used
|
||||||
/// during (de)serialization, that error will be stored and returned here.
|
/// during (de)serialization, that error will be stored and returned here.
|
||||||
Io(io::Error),
|
Io(io::Error),
|
||||||
/// If the bytes in the reader are not decodable because of an invalid
|
/// Returned if the deserializer attempts to deserialize a string that is not valid utf8
|
||||||
/// encoding, this error will be returned. This error is only possible
|
InvalidUtf8Encoding(Utf8Error),
|
||||||
/// if a stream is corrupted. A stream produced from `encode` or `encode_into`
|
/// Returned if the deserializer attempts to deserialize a bool that was
|
||||||
/// should **never** produce an InvalidEncoding error.
|
/// not encoded as either a 1 or a 0
|
||||||
InvalidEncoding {
|
InvalidBoolEncoding(u8),
|
||||||
#[allow(missing_docs)]
|
/// Returned if the deserializer attempts to deserialize a char that is not in the correct format.
|
||||||
desc: &'static str,
|
InvalidCharEncoding,
|
||||||
#[allow(missing_docs)]
|
/// Returned if the deserializer attempts to deserialize the tag of an enum that is
|
||||||
detail: Option<String>
|
/// not in the expected ranges
|
||||||
},
|
InvalidTagEncoding(usize),
|
||||||
/// Serde has a deserialize_any method that lets the format hint to the
|
/// Serde has a deserialize_any method that lets the format hint to the
|
||||||
/// object which route to take in deserializing.
|
/// object which route to take in deserializing.
|
||||||
DeserializeAnyNotSupported,
|
DeserializeAnyNotSupported,
|
||||||
|
|
@ -53,11 +55,14 @@ pub enum ErrorKind {
|
||||||
Custom(String)
|
Custom(String)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl error::Error for ErrorKind {
|
impl StdError for ErrorKind {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
ErrorKind::Io(ref err) => error::Error::description(err),
|
ErrorKind::Io(ref err) => error::Error::description(err),
|
||||||
ErrorKind::InvalidEncoding{desc, ..} => desc,
|
ErrorKind::InvalidUtf8Encoding(_) => "string is not valid utf8",
|
||||||
|
ErrorKind::InvalidBoolEncoding(_) => "invalid u8 while decoding bool",
|
||||||
|
ErrorKind::InvalidCharEncoding => "char is not valid",
|
||||||
|
ErrorKind::InvalidTagEncoding(_) => "tag for enum is not valid",
|
||||||
ErrorKind::SequenceMustHaveLength => "bincode can't encode infinite sequences",
|
ErrorKind::SequenceMustHaveLength => "bincode can't encode infinite sequences",
|
||||||
ErrorKind::DeserializeAnyNotSupported => "bincode doesn't support serde::Deserializer::deserialize_any",
|
ErrorKind::DeserializeAnyNotSupported => "bincode doesn't support serde::Deserializer::deserialize_any",
|
||||||
ErrorKind::SizeLimit => "the size limit for decoding has been reached",
|
ErrorKind::SizeLimit => "the size limit for decoding has been reached",
|
||||||
|
|
@ -69,7 +74,10 @@ impl error::Error for ErrorKind {
|
||||||
fn cause(&self) -> Option<&error::Error> {
|
fn cause(&self) -> Option<&error::Error> {
|
||||||
match *self {
|
match *self {
|
||||||
ErrorKind::Io(ref err) => Some(err),
|
ErrorKind::Io(ref err) => Some(err),
|
||||||
ErrorKind::InvalidEncoding{..} => None,
|
ErrorKind::InvalidUtf8Encoding(_) => None,
|
||||||
|
ErrorKind::InvalidBoolEncoding(_) => None,
|
||||||
|
ErrorKind::InvalidCharEncoding => None,
|
||||||
|
ErrorKind::InvalidTagEncoding(_) => None,
|
||||||
ErrorKind::SequenceMustHaveLength => None,
|
ErrorKind::SequenceMustHaveLength => None,
|
||||||
ErrorKind::DeserializeAnyNotSupported => None,
|
ErrorKind::DeserializeAnyNotSupported => None,
|
||||||
ErrorKind::SizeLimit => None,
|
ErrorKind::SizeLimit => None,
|
||||||
|
|
@ -89,10 +97,14 @@ impl fmt::Display for ErrorKind {
|
||||||
match *self {
|
match *self {
|
||||||
ErrorKind::Io(ref ioerr) =>
|
ErrorKind::Io(ref ioerr) =>
|
||||||
write!(fmt, "io error: {}", ioerr),
|
write!(fmt, "io error: {}", ioerr),
|
||||||
ErrorKind::InvalidEncoding{desc, detail: None}=>
|
ErrorKind::InvalidUtf8Encoding(ref e) =>
|
||||||
write!(fmt, "invalid encoding: {}", desc),
|
write!(fmt, "{}: {}", self.description(), e),
|
||||||
ErrorKind::InvalidEncoding{desc, detail: Some(ref detail)}=>
|
ErrorKind::InvalidBoolEncoding(b) =>
|
||||||
write!(fmt, "invalid encoding: {} ({})", desc, detail),
|
write!(fmt, "{}, expected 0 or 1, found {}", self.description(), b),
|
||||||
|
ErrorKind::InvalidCharEncoding =>
|
||||||
|
write!(fmt, "{}", self.description()),
|
||||||
|
ErrorKind::InvalidTagEncoding(tag) =>
|
||||||
|
write!(fmt, "{}, found {}", self.description(), tag),
|
||||||
ErrorKind::SequenceMustHaveLength =>
|
ErrorKind::SequenceMustHaveLength =>
|
||||||
write!(fmt, "bincode can only encode sequences and maps that have a knowable size ahead of time."),
|
write!(fmt, "bincode can only encode sequences and maps that have a knowable size ahead of time."),
|
||||||
ErrorKind::SizeLimit =>
|
ErrorKind::SizeLimit =>
|
||||||
|
|
|
||||||
|
|
@ -195,25 +195,32 @@ fn test_fixed_size_array() {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn deserializing_errors() {
|
fn deserializing_errors() {
|
||||||
fn isize_invalid_deserialize<T: Debug>(res: Result<T>) {
|
|
||||||
match res.map_err(|e| *e) {
|
match *deserialize_little::<bool>(&vec![0xA][..]).unwrap_err() {
|
||||||
Err(ErrorKind::InvalidEncoding{..}) => {},
|
ErrorKind::InvalidBoolEncoding(0xA) => {},
|
||||||
Err(ErrorKind::Custom(ref s)) if s.contains("invalid encoding") => {},
|
_ => panic!(),
|
||||||
Err(ErrorKind::Custom(ref s)) if s.contains("invalid value") => {},
|
|
||||||
other => panic!("Expecting InvalidEncoding, got {:?}", other),
|
|
||||||
}
|
}
|
||||||
|
match *deserialize_little::<String>(&vec![1, 0, 0, 0, 0, 0, 0, 0, 0xFF][..]).unwrap_err() {
|
||||||
|
ErrorKind::InvalidUtf8Encoding(_) => {},
|
||||||
|
_ => panic!(),
|
||||||
}
|
}
|
||||||
|
|
||||||
isize_invalid_deserialize(deserialize_little::<bool>(&vec![0xA][..]));
|
|
||||||
isize_invalid_deserialize(deserialize_little::<String>(&vec![1, 0, 0, 0, 0, 0, 0, 0, 0xFF][..]));
|
|
||||||
// Out-of-bounds variant
|
// Out-of-bounds variant
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
enum Test {
|
enum Test {
|
||||||
One,
|
One,
|
||||||
Two,
|
Two,
|
||||||
};
|
};
|
||||||
isize_invalid_deserialize(deserialize_little::<Test>(&vec![0, 0, 0, 5][..]));
|
|
||||||
isize_invalid_deserialize(deserialize_little::<Option<u8>>(&vec![5, 0][..]));
|
match *deserialize_little::<Test>(&vec![0, 0, 0, 5][..]).unwrap_err() {
|
||||||
|
// Error message comes from serde
|
||||||
|
ErrorKind::Custom(_) => {},
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
|
match *deserialize_little::<Option<u8>>(&vec![5, 0][..]).unwrap_err() {
|
||||||
|
ErrorKind::InvalidTagEncoding(_) => {},
|
||||||
|
_ => panic!(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue