1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
//! Validation implementations for std types.

use super::{ArchivedBox, ArchivedString, ArchivedVec};
use crate::{
    validation::{ArchiveBoundsContext, ArchiveMemoryContext, LayoutMetadata},
    ArchivePointee, Fallible, RelPtr,
};
use bytecheck::CheckBytes;
use core::fmt;
use ptr_meta::Pointee;
use std::error::Error;

/// Errors that can occur while chechking archived owned pointers
#[derive(Debug)]
pub enum OwnedPointerError<T, R, C> {
    /// The pointer failed to validate due to invalid metadata.
    PointerCheckBytesError(T),
    /// The value pointed to by the owned pointer was invalid.
    ValueCheckBytesError(R),
    /// An error occurred from the validation context.
    ContextError(C),
}

impl<T: fmt::Display, R: fmt::Display, C: fmt::Display> fmt::Display
    for OwnedPointerError<T, R, C>
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            OwnedPointerError::PointerCheckBytesError(e) => e.fmt(f),
            OwnedPointerError::ValueCheckBytesError(e) => e.fmt(f),
            OwnedPointerError::ContextError(e) => e.fmt(f),
        }
    }
}

impl<T: Error + 'static, R: Error + 'static, C: Error + 'static> Error
    for OwnedPointerError<T, R, C>
{
    fn source(&self) -> Option<&(dyn Error + 'static)> {
        match self {
            OwnedPointerError::PointerCheckBytesError(e) => Some(e as &dyn Error),
            OwnedPointerError::ValueCheckBytesError(e) => Some(e as &dyn Error),
            OwnedPointerError::ContextError(e) => Some(e as &dyn Error),
        }
    }
}

type CheckOwnedPointerError<T, C> = OwnedPointerError<
    <<T as ArchivePointee>::ArchivedMetadata as CheckBytes<C>>::Error,
    <T as CheckBytes<C>>::Error,
    <C as Fallible>::Error,
>;

impl<C: ArchiveBoundsContext + ArchiveMemoryContext + ?Sized> CheckBytes<C> for ArchivedString
where
    C::Error: Error,
{
    type Error = CheckOwnedPointerError<str, C>;

    unsafe fn check_bytes<'a>(
        value: *const Self,
        context: &mut C,
    ) -> Result<&'a Self, Self::Error> {
        let rel_ptr = RelPtr::<str>::manual_check_bytes(value.cast(), context)
            .map_err(OwnedPointerError::PointerCheckBytesError)?;
        let ptr = context
            .claim_owned_rel_ptr(rel_ptr)
            .map_err(OwnedPointerError::ContextError)?;
        <str as CheckBytes<C>>::check_bytes(ptr, context)
            .map_err(OwnedPointerError::ValueCheckBytesError)?;
        Ok(&*value)
    }
}

impl<
        T: ArchivePointee + CheckBytes<C> + Pointee + ?Sized,
        C: ArchiveBoundsContext + ArchiveMemoryContext + ?Sized,
    > CheckBytes<C> for ArchivedBox<T>
where
    T::ArchivedMetadata: CheckBytes<C>,
    C::Error: Error,
    <T as Pointee>::Metadata: LayoutMetadata<T>,
{
    type Error =
        OwnedPointerError<<T::ArchivedMetadata as CheckBytes<C>>::Error, T::Error, C::Error>;

    unsafe fn check_bytes<'a>(
        value: *const Self,
        context: &mut C,
    ) -> Result<&'a Self, Self::Error> {
        let rel_ptr = RelPtr::<T>::manual_check_bytes(value.cast(), context)
            .map_err(OwnedPointerError::PointerCheckBytesError)?;
        let ptr = context
            .claim_owned_rel_ptr(rel_ptr)
            .map_err(OwnedPointerError::ContextError)?;
        T::check_bytes(ptr, context).map_err(OwnedPointerError::ValueCheckBytesError)?;
        Ok(&*value)
    }
}

impl<T: CheckBytes<C>, C: ArchiveBoundsContext + ArchiveMemoryContext + ?Sized> CheckBytes<C>
    for ArchivedVec<T>
where
    [T]: ArchivePointee,
    <[T] as ArchivePointee>::ArchivedMetadata: CheckBytes<C>,
    C::Error: Error,
    <[T] as Pointee>::Metadata: LayoutMetadata<[T]>,
{
    type Error = CheckOwnedPointerError<[T], C>;

    unsafe fn check_bytes<'a>(
        value: *const Self,
        context: &mut C,
    ) -> Result<&'a Self, Self::Error> {
        let rel_ptr = RelPtr::<[T]>::manual_check_bytes(value.cast(), context)
            .map_err(OwnedPointerError::PointerCheckBytesError)?;
        let ptr = context
            .claim_owned_rel_ptr(rel_ptr)
            .map_err(OwnedPointerError::ContextError)?;
        <[T]>::check_bytes(ptr, context).map_err(OwnedPointerError::ValueCheckBytesError)?;
        Ok(&*value)
    }
}