Improved de/serialise error messages

Fortune for rsh's current commit: Half curse − 半凶
complex-cap
Avril 3 years ago
parent 46cd0e4a9f
commit 37a00d1099
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -9,6 +9,25 @@ use bytes::{
Buf, Buf,
}; };
macro_rules! try_from {
(ref $into:ty, $from:expr $(; $fmt:literal)?) => {
{
let from = &$from;
#[inline] fn _type_name_of_val<T: ?Sized>(_: &T) -> &'static str
{
::std::any::type_name::<T>()
}
<$into>::try_from(*from).wrap_err(eyre!("Failed to convert type"))
.with_section(|| ::std::any::type_name::<$into>().header("New type"))
.with_section(|| _type_name_of_val(from).header("Old type"))
.with_section(|| from.to_string().header("Value was"))
}
};
}
/// Check bit written/read from binary streams to check basic integrity.
pub const MESSAGE_HEADER_CHECK: [u8; 4] = (0xc0ffee00u32).to_be_bytes();
impl<V: ?Sized> SerializedMessage<V> impl<V: ?Sized> SerializedMessage<V>
{ {
/// Write this message to a buffer /// Write this message to a buffer
@ -41,15 +60,22 @@ impl<V: ?Sized> SerializedMessage<V>
(: $ser:expr) => { (: $ser:expr) => {
{ {
let mut v = StackVec::new(); let mut v = StackVec::new();
serde_cbor::to_writer(&mut v, $ser)?; #[inline] fn _type_name_of_val<T: ?Sized>(_: &T) -> &'static str
buffer.put_u64(v.len().try_into()?); {
::std::any::type_name::<T>()
}
let ser = $ser;
serde_cbor::to_writer(&mut v, $ser)
.wrap_err(eyre!("Failed to serialise value to temporary buffer"))
.with_section(|| _type_name_of_val(ser).header("Type was"))?;
buffer.put_u64(try_from!(ref u64, v.len())?);
write!(&v[..]); write!(&v[..]);
} }
}; };
} }
write!(MESSAGE_HEADER_CHECK);
write!(: &self.header); write!(: &self.header);
buffer.put_u64(self.data.len().try_into()?); buffer.put_u64(try_from!(ref u64, self.data.len())?);
write!(self.data); write!(self.data);
write!(self.hash); write!(self.hash);
write!(? self.enc_key); write!(? self.enc_key);
@ -93,21 +119,21 @@ impl<V: ?Sized + MessageValue> SerializedMessage<V>
Some(def) Some(def)
}, },
x => { x => {
return Err(eyre!("Invalid optional-set bit: {}", x)); return Err(eyre!("Invalid optional-set bit (should be 0 or 1)").with_section(|| x.header("Value was")));
} }
} }
} }
}; };
(: $ser:ty) => { (: $ser:ty) => {
{ {
let len = usize::try_from(bytes.get_u64())?; let len = try_from!(ref usize, bytes.get_u64())?;
if len > MAX_ALLOC_SIZE { if len > MAX_ALLOC_SIZE {
return Err(eyre!("Invalid length read: {}", len) return Err(eyre!("Invalid length read: {}", len)
.with_section(|| format!("Max length read: {}", MAX_ALLOC_SIZE))) .with_section(|| format!("Max length read: {}", MAX_ALLOC_SIZE)))
} }
alloc_local_bytes(len, |de| { alloc_local_bytes(len, |de| {
read!(&mut de[..]); read!(&mut de[..]);
serde_cbor::from_slice::<$ser>(&de[..]).wrap_err(eyre!("Failed to deserialise {} from reader", std::any::type_name::<$ser>())) serde_cbor::from_slice::<$ser>(&de[..]).wrap_err(eyre!("Failed to deserialise CBOR from reader")).with_section(|| std::any::type_name::<$ser>().header("Type to deserialise was"))
})? })?
} }
@ -120,13 +146,22 @@ impl<V: ?Sized + MessageValue> SerializedMessage<V>
} }
} }
} }
let mut check = [0u8; MESSAGE_HEADER_CHECK.len()];
read!(&mut check[..]);
if check != MESSAGE_HEADER_CHECK {
return Err(eyre!("Invalid check bit for message header"))
.with_section(|| u32::from_be_bytes(check).header("Expected"))
.with_section(|| u32::from_be_bytes(MESSAGE_HEADER_CHECK).header("Got"));
}
let header = read!(: SerHeader); let header = read!(: SerHeader);
let data_len = usize::try_from(bytes.get_u64())?; let data_len = try_from!(ref usize, bytes.get_u64())?;
let mut data = Vec::with_capacity(std::cmp::min(data_len, MAX_ALLOC_SIZE)); //XXX: Redesign so we don't allocate OR try to read massive buffers by accident on corrupted/malformed messages let mut data = Vec::with_capacity(std::cmp::min(data_len, MAX_ALLOC_SIZE)); //XXX: Redesign so we don't allocate OR try to read massive buffers by accident on corrupted/malformed messages
read!(&mut data, data_len); read!(&mut data, data_len);
if data.len()!=data_len { if data.len()!=data_len {
return Err(eyre!("Failed to read {} bytes from buffer (got {})", data_len, data.len())); return Err(eyre!("Failed to read body bytes from buffer"))
.with_section(|| format!("{} bytes", data_len).header("Tried to read"))
.with_section(|| format!("{} bytes", data.len()).header("Read only"));
} }
let mut hash = sha256::Sha256Hash::default(); let mut hash = sha256::Sha256Hash::default();
read!(&mut hash); read!(&mut hash);

Loading…
Cancel
Save