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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
//! The `guard` module exposes an API for memory boundary checking.
//!
//! # Examples:
//!
//! In order to check whether a value would fit in the given
//! slice with no extra trailing bytes:
//!
//! ```
//! # use safe_transmute::error::GuardError;
//! # use safe_transmute::guard::{SingleValueGuard, Guard};
//! # fn run() -> Result<(), GuardError> {
//! SingleValueGuard::check::<u32>(&[0x00, 0x01, 0x00, 0x02])?;
//! # Ok(())
//! # }
//! # run().unwrap();
//! ```
//!
//! Different guard types implement different checking strategies.
//! For example, the pedantic guard type [`PedanticGuard`](struct.PedanticGuard.html) requires
//! the slice to have space for at least one value, and not have
//! extraneous bytes at the end.
//!
//! ```
//! # use safe_transmute::error::GuardError;
//! # use safe_transmute::guard::{PedanticGuard, Guard};
//! # fn run() -> Result<(), GuardError> {
//! PedanticGuard::check::<u16>(&[0xAA, 0xAA, 0xBB, 0xBB, 0xCC, 0xCC])?;
//! # Ok(())
//! # }
//! # run().unwrap();
//! ```
//!
//! [`PermissiveGuard`](struct.PermissiveGuard.html), on the other hand, will accept any memory slice.
//!
//! ```
//! # use safe_transmute::error::GuardError;
//! # use safe_transmute::guard::{PermissiveGuard, Guard};
//! # fn run() -> Result<(), GuardError> {
//! PermissiveGuard::check::<i16>(b"covfefe")?;
//! # Ok(())
//! # }
//! # run().unwrap();
//! ```
//!
//! If the check fails, the resulting [`GuardError`](../type.GuardError.html) value describes why.
//!
//! ```
//! # use safe_transmute::{GuardError, ErrorReason};
//! # use safe_transmute::guard::{PedanticGuard, Guard};
//! assert_eq!(PedanticGuard::check::<i16>(b"covfefe"),
//!            Err(GuardError {
//!                required: 2,
//!                actual: 7,
//!                reason: ErrorReason::InexactByteCount,
//!            }));
//! ```
//!
//! # Note
//!
//! Regardless of the chosen strategy, guarded transmutation functions will
//! always ensure that no out of bounds access is attempted. All functions will
//! restrict the output to spatially safe portions of the input. The guard
//! API exists to establish expectations in the conversion process.


use error::{ErrorReason, GuardError};
use core::mem::size_of;


/// The trait describes types which define boundary checking strategies.
/// See the [module-level documentation](index.html) for more details.
pub trait Guard {
    /// Check the size of the given byte slice against a particular type.
    ///
    /// # Errors
    ///
    /// If the slice's size does not comply with this guard, an error
    /// which specifies the incompatibility is returned.
    fn check<T>(v: &[u8]) -> Result<(), GuardError>;
}


/// Single value guard: The byte slice must have exactly enough bytes to fill a single
/// instance of a type.
pub struct SingleValueGuard;

impl Guard for SingleValueGuard {
    fn check<T>(bytes: &[u8]) -> Result<(), GuardError> {
        if bytes.len() != size_of::<T>() {
            Err(GuardError {
                required: size_of::<T>(),
                actual: bytes.len(),
                reason: ErrorReason::InexactByteCount,
            })
        } else {
            Ok(())
        }
    }
}


/// Pedantic guard: The byte slice must have at least enough bytes to fill a single
/// instance of a type, and should not have extraneous data.
pub struct PedanticGuard;

impl Guard for PedanticGuard {
    fn check<T>(bytes: &[u8]) -> Result<(), GuardError> {
        if bytes.len() < size_of::<T>() {
            Err(GuardError {
                required: size_of::<T>(),
                actual: bytes.len(),
                reason: ErrorReason::NotEnoughBytes,
            })
        } else if (size_of::<T>() == 0 && bytes.len() != 0) || (size_of::<T>() != 0 && bytes.len() % size_of::<T>() != 0) {
            Err(GuardError {
                required: size_of::<T>(),
                actual: bytes.len(),
                reason: ErrorReason::InexactByteCount,
            })
        } else {
            Ok(())
        }
    }
}


/// An all-or-nothing guard: The byte slice should not have extraneous data, but can be
/// empty, unlike `PedanticGuard`.
pub struct AllOrNothingGuard;

impl Guard for AllOrNothingGuard {
    fn check<T>(bytes: &[u8]) -> Result<(), GuardError> {
        if (size_of::<T>() == 0 && bytes.len() != 0) || (size_of::<T>() != 0 && bytes.len() % size_of::<T>() != 0) {
            Err(GuardError {
                required: size_of::<T>(),
                actual: bytes.len(),
                reason: ErrorReason::InexactByteCount,
            })
        } else {
            Ok(())
        }
    }
}


/// A single-or-many guard: The byte slice must have at least enough bytes to fill a single
/// instance of a type, and extraneous data is ignored.
pub struct SingleManyGuard;

impl Guard for SingleManyGuard {
    fn check<T>(bytes: &[u8]) -> Result<(), GuardError> {
        if bytes.len() < size_of::<T>() {
            Err(GuardError {
                required: size_of::<T>(),
                actual: bytes.len(),
                reason: ErrorReason::NotEnoughBytes,
            })
        } else {
            Ok(())
        }
    }
}


/// Permissive guard: The resulting slice would have as many instances of a type as will
/// fit, rounded down. Therefore, this guard will never yield an error.
pub struct PermissiveGuard;

impl Guard for PermissiveGuard {
    #[inline]
    fn check<T>(_: &[u8]) -> Result<(), GuardError> {
        Ok(())
    }
}