// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: Apache-2.0 use s2n_codec::{DecoderBufferMut as Inner, DecoderError, DecoderValue, DecoderValueMut}; /// A BPF-aware version of [`s2n_codec::DecoderBufferMut`] /// /// The Linux BPF verifier requires that every pointer be checked against the `end` pointer. This /// means that it struggles with regular Rust slices that use `ptr + len` instead of `ptr + end`. pub struct DecoderBufferMut<'a> { buffer: Inner<'a>, end: *mut u8, } impl<'a> DecoderBufferMut<'a> { /// Creates a new DecoderBufferMut. /// /// # Safety /// /// The `start` and `end` pointers must be a valid range of bytes, ideally directly coming /// from the BPF/XDP context argument. #[inline] pub unsafe fn new(start: *mut u8, end: *mut u8) -> Self { let len = end as usize - start as usize; let data = core::slice::from_raw_parts_mut(start, len); let buffer = Inner::new(data); Self { buffer, end } } /// Validates that the starting pointer is still within the bounds of the end pointer #[inline] fn new_checked(buffer: Inner<'a>, end: *mut u8) -> Result { // The Linux BPF verifier needs to prove that no pointers go beyond the "end" pointer if buffer.as_less_safe_slice().as_ptr() > end { return Err(DecoderError::UnexpectedEof(0)); } Ok(Self { buffer, end }) } /// Decodes a T from the buffer, if possible #[inline] pub fn decode>(self) -> Result<(T, Self), DecoderError> { let end = self.end; let (v, buffer) = self.buffer.decode()?; let buffer = Self::new_checked(buffer, end)?; Ok((v, buffer)) } /// Decodes a slice of bytes with the given len, if possible #[inline] pub fn decode_slice(self, len: usize) -> Result<(Self, Self), DecoderError> { let end = self.end; let (slice, buffer) = self.buffer.decode_slice(len)?; let slice = Self::new_checked(slice, end)?; let buffer = Self::new_checked(buffer, end)?; Ok((slice, buffer)) } #[inline] pub fn into_less_safe_slice(self) -> &'a mut [u8] { self.buffer.into_less_safe_slice() } #[inline] pub fn len(&self) -> usize { self.buffer.len() } #[inline] pub fn is_empty(&self) -> bool { self.buffer.is_empty() } } /// A generic interface over a decoder buffer pub trait Decoder<'a>: Sized { fn decode + DecoderValueMut<'a>>( self, ) -> core::result::Result<(T, Self), DecoderError>; fn decode_slice(self, len: usize) -> core::result::Result<(Self, Self), DecoderError>; } impl<'a> Decoder<'a> for DecoderBufferMut<'a> { #[inline] fn decode + DecoderValueMut<'a>>( self, ) -> core::result::Result<(T, Self), DecoderError> { Self::decode(self) } #[inline] fn decode_slice(self, len: usize) -> core::result::Result<(Self, Self), DecoderError> { Self::decode_slice(self, len) } } impl<'a> Decoder<'a> for s2n_codec::DecoderBuffer<'a> { #[inline] fn decode + DecoderValueMut<'a>>( self, ) -> core::result::Result<(T, Self), DecoderError> { Self::decode(self) } #[inline] fn decode_slice(self, len: usize) -> core::result::Result<(Self, Self), DecoderError> { Self::decode_slice(self, len) } } impl<'a> Decoder<'a> for s2n_codec::DecoderBufferMut<'a> { #[inline] fn decode + DecoderValueMut<'a>>( self, ) -> core::result::Result<(T, Self), DecoderError> { Self::decode(self) } #[inline] fn decode_slice(self, len: usize) -> core::result::Result<(Self, Self), DecoderError> { Self::decode_slice(self, len) } }