diff options
author | Casper <casperneo@uchicago.edu> | 2020-12-07 18:37:51 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-07 18:37:51 -0500 |
commit | 442949bc11c4e08a04516390dd78794cd4dec746 (patch) | |
tree | 292275b264f5e50a31255a979e5a0c6cd7ee0ca0 /samples | |
parent | 9064072e8cd42be6710b293ad567acd44845f7fc (diff) | |
download | flatbuffers-442949bc11c4e08a04516390dd78794cd4dec746.tar.gz flatbuffers-442949bc11c4e08a04516390dd78794cd4dec746.tar.bz2 flatbuffers-442949bc11c4e08a04516390dd78794cd4dec746.zip |
Rust Flatbuffers Verifier (#6269)
* Updated comments and fixed a fundemental type error.
* bump rust flatbuffers semver
* Initial commit with verifier, need to clean up
* Verifier tested. Needs clean up and refactoring.
* Display for InvalidFlatbuffer and better errors for strings
* SimpleToVerify, some refactoring
* Combined VerifierType TableAccessorFuncBody into FollowType
* scrub todos
* Update Rust get_root functions.
There are 6 variants, with verifier options, default verifier options
and no verification "fast".
* Rename root fns
* inline
* Update to use thiserror
* fix for bad compiler
* improve error formatting
* Replace multiply with saturating_multiply
* saturating adds too
* Add docs disclaiming experimental verification system
Co-authored-by: Casper Neo <cneo@google.com>
Diffstat (limited to 'samples')
-rw-r--r-- | samples/monster_generated.rs | 161 | ||||
-rw-r--r-- | samples/sample_binary.rs | 5 |
2 files changed, 151 insertions, 15 deletions
diff --git a/samples/monster_generated.rs b/samples/monster_generated.rs index e352b758..53070c0d 100644 --- a/samples/monster_generated.rs +++ b/samples/monster_generated.rs @@ -77,7 +77,8 @@ impl<'a> flatbuffers::Follow<'a> for Color { type Inner = Self; #[inline] fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self(flatbuffers::read_scalar_at::<i8>(buf, loc)) + let b = flatbuffers::read_scalar_at::<i8>(buf, loc); + Self(b) } } @@ -92,14 +93,27 @@ impl flatbuffers::Push for Color { impl flatbuffers::EndianScalar for Color { #[inline] fn to_little_endian(self) -> Self { - Self(i8::to_le(self.0)) + let b = i8::to_le(self.0); + Self(b) } #[inline] fn from_little_endian(self) -> Self { - Self(i8::from_le(self.0)) + let b = i8::from_le(self.0); + Self(b) } } +impl<'a> flatbuffers::Verifiable for Color { + #[inline] + fn run_verifier<'o, 'b>( + v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + i8::run_verifier(v, pos) + } +} + +impl flatbuffers::SimpleToVerifyInSlice for Color {} #[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")] pub const ENUM_MIN_EQUIPMENT: u8 = 0; #[deprecated(since = "1.13", note = "Use associated constants instead. This will no longer be generated in 2021.")] @@ -143,11 +157,13 @@ impl std::fmt::Debug for Equipment { } } } +pub struct EquipmentUnionTableOffset {} impl<'a> flatbuffers::Follow<'a> for Equipment { type Inner = Self; #[inline] fn follow(buf: &'a [u8], loc: usize) -> Self::Inner { - Self(flatbuffers::read_scalar_at::<u8>(buf, loc)) + let b = flatbuffers::read_scalar_at::<u8>(buf, loc); + Self(b) } } @@ -162,15 +178,27 @@ impl flatbuffers::Push for Equipment { impl flatbuffers::EndianScalar for Equipment { #[inline] fn to_little_endian(self) -> Self { - Self(u8::to_le(self.0)) + let b = u8::to_le(self.0); + Self(b) } #[inline] fn from_little_endian(self) -> Self { - Self(u8::from_le(self.0)) + let b = u8::from_le(self.0); + Self(b) } } -pub struct EquipmentUnionTableOffset {} +impl<'a> flatbuffers::Verifiable for Equipment { + #[inline] + fn run_verifier<'o, 'b>( + v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + u8::run_verifier(v, pos) + } +} + +impl flatbuffers::SimpleToVerifyInSlice for Equipment {} // struct Vec3, aligned to 4 #[repr(C, align(4))] #[derive(Clone, Copy, PartialEq)] @@ -189,6 +217,7 @@ impl std::fmt::Debug for Vec3 { } } +impl flatbuffers::SimpleToVerifyInSlice for Vec3 {} impl flatbuffers::SafeSliceAccess for Vec3 {} impl<'a> flatbuffers::Follow<'a> for Vec3 { type Inner = &'a Vec3; @@ -226,7 +255,15 @@ impl<'b> flatbuffers::Push for &'b Vec3 { } } - +impl<'a> flatbuffers::Verifiable for Vec3 { + #[inline] + fn run_verifier<'o, 'b>( + v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.in_buffer::<Self>(pos) + } +} impl Vec3 { pub fn new(_x: f32, _y: f32, _z: f32) -> Self { Vec3 { @@ -324,7 +361,7 @@ impl<'a> Monster<'a> { } #[inline] pub fn weapons(&self) -> Option<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon<'a>>>> { - self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<flatbuffers::ForwardsUOffset<Weapon<'a>>>>>(Monster::VT_WEAPONS, None) + self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, flatbuffers::ForwardsUOffset<Weapon>>>>(Monster::VT_WEAPONS, None) } #[inline] pub fn equipped_type(&self) -> Equipment { @@ -336,7 +373,7 @@ impl<'a> Monster<'a> { } #[inline] pub fn path(&self) -> Option<&'a [Vec3]> { - self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<Vec3>>>(Monster::VT_PATH, None).map(|v| v.safe_slice() ) + self._tab.get::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'a, Vec3>>>(Monster::VT_PATH, None).map(|v| v.safe_slice()) } #[inline] #[allow(non_snake_case)] @@ -350,6 +387,31 @@ impl<'a> Monster<'a> { } +impl flatbuffers::Verifiable for Monster<'_> { + #[inline] + fn run_verifier<'o, 'b>( + v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::<Vec3>(&"pos", Self::VT_POS, false)? + .visit_field::<i16>(&"mana", Self::VT_MANA, false)? + .visit_field::<i16>(&"hp", Self::VT_HP, false)? + .visit_field::<flatbuffers::ForwardsUOffset<&str>>(&"name", Self::VT_NAME, false)? + .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, u8>>>(&"inventory", Self::VT_INVENTORY, false)? + .visit_field::<Color>(&"color", Self::VT_COLOR, false)? + .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, flatbuffers::ForwardsUOffset<Weapon>>>>(&"weapons", Self::VT_WEAPONS, false)? + .visit_union::<Equipment, _>(&"equipped_type", Self::VT_EQUIPPED_TYPE, &"equipped", Self::VT_EQUIPPED, false, |key, v, pos| { + match key { + Equipment::Weapon => v.verify_union_variant::<flatbuffers::ForwardsUOffset<Weapon>>("Equipment::Weapon", pos), + _ => Ok(()), + } + })? + .visit_field::<flatbuffers::ForwardsUOffset<flatbuffers::Vector<'_, Vec3>>>(&"path", Self::VT_PATH, false)? + .finish(); + Ok(()) + } +} pub struct MonsterArgs<'a> { pub pos: Option<&'a Vec3>, pub mana: i16, @@ -512,6 +574,19 @@ impl<'a> Weapon<'a> { } } +impl flatbuffers::Verifiable for Weapon<'_> { + #[inline] + fn run_verifier<'o, 'b>( + v: &mut flatbuffers::Verifier<'o, 'b>, pos: usize + ) -> Result<(), flatbuffers::InvalidFlatbuffer> { + use self::flatbuffers::Verifiable; + v.visit_table(pos)? + .visit_field::<flatbuffers::ForwardsUOffset<&str>>(&"name", Self::VT_NAME, false)? + .visit_field::<i16>(&"damage", Self::VT_DAMAGE, false)? + .finish(); + Ok(()) + } +} pub struct WeaponArgs<'a> { pub name: Option<flatbuffers::WIPOffset<&'a str>>, pub damage: i16, @@ -562,16 +637,78 @@ impl std::fmt::Debug for Weapon<'_> { } } #[inline] +#[deprecated(since="1.13", note="Deprecated in favor of `root_as...` methods.")] pub fn get_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> { - flatbuffers::get_root::<Monster<'a>>(buf) + unsafe { flatbuffers::root_unchecked::<Monster<'a>>(buf) } } #[inline] +#[deprecated(since="1.13", note="Deprecated in favor of `root_as...` methods.")] pub fn get_size_prefixed_root_as_monster<'a>(buf: &'a [u8]) -> Monster<'a> { - flatbuffers::get_size_prefixed_root::<Monster<'a>>(buf) + unsafe { flatbuffers::size_prefixed_root_unchecked::<Monster<'a>>(buf) } } #[inline] +/// Verifies that a buffer of bytes contains a `Monster` +/// and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_monster_unchecked`. +pub fn root_as_monster(buf: &[u8]) -> Result<Monster, flatbuffers::InvalidFlatbuffer> { + flatbuffers::root::<Monster>(buf) +} +#[inline] +/// Verifies that a buffer of bytes contains a size prefixed +/// `Monster` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `size_prefixed_root_as_monster_unchecked`. +pub fn size_prefixed_root_as_monster(buf: &[u8]) -> Result<Monster, flatbuffers::InvalidFlatbuffer> { + flatbuffers::size_prefixed_root::<Monster>(buf) +} +#[inline] +/// Verifies, with the given options, that a buffer of bytes +/// contains a `Monster` and returns it. +/// Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_monster_unchecked`. +pub fn root_as_monster_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result<Monster<'b>, flatbuffers::InvalidFlatbuffer> { + flatbuffers::root_with_opts::<Monster<'b>>(opts, buf) +} +#[inline] +/// Verifies, with the given verifier options, that a buffer of +/// bytes contains a size prefixed `Monster` and returns +/// it. Note that verification is still experimental and may not +/// catch every error, or be maximally performant. For the +/// previous, unchecked, behavior use +/// `root_as_monster_unchecked`. +pub fn size_prefixed_root_as_monster_with_opts<'b, 'o>( + opts: &'o flatbuffers::VerifierOptions, + buf: &'b [u8], +) -> Result<Monster<'b>, flatbuffers::InvalidFlatbuffer> { + flatbuffers::size_prefixed_root_with_opts::<Monster<'b>>(opts, buf) +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a Monster and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid `Monster`. +pub unsafe fn root_as_monster_unchecked(buf: &[u8]) -> Monster { + flatbuffers::root_unchecked::<Monster>(buf) +} +#[inline] +/// Assumes, without verification, that a buffer of bytes contains a size prefixed Monster and returns it. +/// # Safety +/// Callers must trust the given bytes do indeed contain a valid size prefixed `Monster`. +pub unsafe fn size_prefixed_root_as_monster_unchecked(buf: &[u8]) -> Monster { + flatbuffers::size_prefixed_root_unchecked::<Monster>(buf) +} +#[inline] pub fn finish_monster_buffer<'a, 'b>( fbb: &'b mut flatbuffers::FlatBufferBuilder<'a>, root: flatbuffers::WIPOffset<Monster<'a>>) { diff --git a/samples/sample_binary.rs b/samples/sample_binary.rs index 6fb987eb..649babf3 100644 --- a/samples/sample_binary.rs +++ b/samples/sample_binary.rs @@ -20,8 +20,7 @@ extern crate flatbuffers; // import the generated code #[path = "./monster_generated.rs"] mod monster_generated; -pub use monster_generated::my_game::sample::{get_root_as_monster, - Color, Equipment, +pub use monster_generated::my_game::sample::{Color, Equipment, Monster, MonsterArgs, Vec3, Weapon, WeaponArgs}; @@ -98,7 +97,7 @@ fn main() { let buf = builder.finished_data(); // Of type `&[u8]` // Get access to the root: - let monster = get_root_as_monster(buf); + let monster = flatbuffers::root::<Monster>(buf).unwrap(); // Get and test some scalar types from the FlatBuffer. let hp = monster.hp(); |