Skip to content

Commit

Permalink
validate serialized capabilities
Browse files Browse the repository at this point in the history
  • Loading branch information
Alex Coats committed Nov 1, 2023
1 parent 776e3e6 commit 6431728
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 15 deletions.
36 changes: 21 additions & 15 deletions sdk/src/types/block/capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ use core::marker::PhantomData;

use derive_more::Deref;
use packable::{
error::UnpackErrorExt,
error::{UnpackError, UnpackErrorExt},
prefix::{BoxedSlicePrefix, UnpackPrefixError},
Packable,
};

use crate::types::block::Error;

/// A list of bitflags that represent capabilities.
#[derive(Debug, Deref)]
#[repr(transparent)]
Expand All @@ -21,13 +23,17 @@ pub struct Capabilities<Flag> {
}

impl<Flag> Capabilities<Flag> {
pub(crate) fn from_bytes(bytes: BoxedSlicePrefix<u8, u8>) -> Self {
let mut res = Self {
/// Try to create capabilities from serialized bytes. Bytes with trailing zeroes are invalid.
pub(crate) fn from_bytes(bytes: BoxedSlicePrefix<u8, u8>) -> Result<Self, Error> {
if let Some(idx) = bytes.iter().rposition(|c| 0.ne(c)) {
if idx + 1 < bytes.len() {
return Err(Error::TrailingCapabilityBytes);
}
}
Ok(Self {
bytes,
_flag: PhantomData,
};
res.trim();
res
})
}

/// Returns a [`Capabilities`] with every possible flag disabled.
Expand Down Expand Up @@ -196,25 +202,22 @@ impl<Flag: 'static> Packable for Capabilities<Flag> {
type UnpackVisitor = ();

fn pack<P: packable::packer::Packer>(&self, packer: &mut P) -> Result<(), P::Error> {
if !self.is_none() {
self.bytes.pack(packer)?;
} else {
0_u8.pack(packer)?;
}
self.bytes.pack(packer)?;
Ok(())
}

fn unpack<U: packable::unpacker::Unpacker, const VERIFY: bool>(
unpacker: &mut U,
visitor: &Self::UnpackVisitor,
) -> Result<Self, packable::error::UnpackError<Self::UnpackError, U::Error>> {
Ok(Self::from_bytes(
) -> Result<Self, UnpackError<Self::UnpackError, U::Error>> {
Self::from_bytes(
BoxedSlicePrefix::unpack::<_, VERIFY>(unpacker, visitor)
.map_packable_err(|e| match e {
UnpackPrefixError::Item(i) | UnpackPrefixError::Prefix(i) => i,
})
.coerce()?,
))
)
.map_err(UnpackError::Packable)
}
}

Expand Down Expand Up @@ -251,7 +254,10 @@ mod serde {
where
D: ::serde::Deserializer<'de>,
{
crate::utils::serde::boxed_slice_prefix_hex_bytes::deserialize(deserializer).map(Self::from_bytes)
Self::from_bytes(crate::utils::serde::boxed_slice_prefix_hex_bytes::deserialize(
deserializer,
)?)
.map_err(::serde::de::Error::custom)
}
}
}
2 changes: 2 additions & 0 deletions sdk/src/types/block/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ pub enum Error {
created: EpochIndex,
target: EpochIndex,
},
TrailingCapabilityBytes,
}

#[cfg(feature = "std")]
Expand Down Expand Up @@ -397,6 +398,7 @@ impl fmt::Display for Error {
Self::InvalidEpochDelta { created, target } => {
write!(f, "invalid epoch delta: created {created}, target {target}")
}
Self::TrailingCapabilityBytes => write!(f, "capabilities bytes has trailing zeroes"),
}
}
}
Expand Down

0 comments on commit 6431728

Please sign in to comment.