@ -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 ] = ( 0xc0ffee00 u32 ) . 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 = [ 0 u8 ; 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 ) ;