Expand description
bytecheck
bytecheck is a type validation framework for Rust.
For some types, creating an invalid value immediately results in undefined behavior. This can cause some issues when trying to validate potentially invalid bytes, as just casting the bytes to your type can technically cause errors. This makes it difficult to write validation routines, because until you’re certain that the bytes represent valid values you cannot cast them.
bytecheck provides a framework for performing these byte-level validations and implements checks for basic types along with a derive macro to implement validation for custom structs and enums.
Design
CheckBytes
is at the heart of bytecheck, and does the heavy lifting of
verifying that some bytes represent a valid type. Implementing it can be
done manually or automatically with the derive macro.
Examples
use bytecheck::CheckBytes;
#[derive(CheckBytes, Debug)]
struct Test {
a: u32,
b: bool,
c: char,
}
#[repr(C, align(16))]
struct Aligned<const N: usize>([u8; N]);
macro_rules! bytes {
($($byte:literal,)*) => {
(&Aligned([$($byte,)*]).0 as &[u8]).as_ptr()
};
($($byte:literal),*) => {
bytes!($($byte,)*)
};
}
// This type is laid out as (u32, char, bool)
// In this example, the architecture is assumed to be little-endian
unsafe {
// These are valid bytes for (0, 'x', true)
Test::check_bytes(
bytes![
0u8, 0u8, 0u8, 0u8, 0x78u8, 0u8, 0u8, 0u8,
1u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8
].cast(),
&mut ()
).unwrap();
// Changing the bytes for the u32 is OK, any bytes are a valid u32
Test::check_bytes(
bytes![
42u8, 16u8, 20u8, 3u8, 0x78u8, 0u8, 0u8, 0u8,
1u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8
].cast(),
&mut ()
).unwrap();
// Characters outside the valid ranges are invalid
Test::check_bytes(
bytes![
0u8, 0u8, 0u8, 0u8, 0x00u8, 0xd8u8, 0u8, 0u8,
1u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8
].cast(),
&mut ()
).unwrap_err();
Test::check_bytes(
bytes![
0u8, 0u8, 0u8, 0u8, 0x00u8, 0x00u8, 0x11u8, 0u8,
1u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8
].cast(),
&mut ()
).unwrap_err();
// 0 is a valid boolean value (false) but 2 is not
Test::check_bytes(
bytes![
0u8, 0u8, 0u8, 0u8, 0x78u8, 0u8, 0u8, 0u8,
0u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8
].cast(),
&mut ()
).unwrap();
Test::check_bytes(
bytes![
0u8, 0u8, 0u8, 0u8, 0x78u8, 0u8, 0u8, 0u8,
2u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8, 255u8
].cast(),
&mut ()
).unwrap_err();
}
Features
verbose
: Some validation algorithms are optimized for speed and do not report full error details by default. This feature provides full error information.std
: Enables standard library support (enabled by default). If thestd
feature is not enabled, thealloc
crate is required.
Crate support
Some common crates need to be supported by bytecheck before an official integration has been made. Support is provided by bytecheck for these crates, but in the future crates should depend on bytecheck and provide their own implementations. The crates that already have support provided by bytecheck should work toward integrating the implementations into themselves.
Crates supported by bytecheck:
Structs
- An error resulting from an invalid array.
- An error resulting from an invalid boolean.
- An error resulting from an invalid character.
- An error resulting from an invalid struct.
- An error resulting from an invalid tuple struct.
Enums
- An error resulting from an invalid
CStr
. - An error resulting from an invalid enum.
- An error resulting from an invalid
NonZero
integer. - An error resulting from an invalid slice.
- An error resulting from an invalid str.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
- An error resulting from an invalid tuple.
Traits
- A type that can check whether a pointer points to a valid value.
- An error that can be debugged and displayed.
Type Definitions
- The type used for boxing errors.
Derive Macros
- Derives
CheckBytes
for the labeled type.