Commit Graph
7 Commits
Author SHA1 Message Date
Artyom Palvelev 5eb190f000 rust: fix 64-bit scalar wire-format alignment on 32-bit targets in Push::alignment (#9465)
In the FlatBuffers binary wire format specification, every scalar field is
aligned to its own byte size (`1`, `2`, `4`, or `8` bytes), regardless of the
host CPU architecture. Both the `flatc` schema compiler (when computing table
`max_align` and struct field offsets) and the C++ `FlatBufferBuilder::Align` /
`PushElement` implementation align 64-bit scalars (`u64`, `i64`, `f64`) to 8
bytes on all architectures.

However, in the Rust `flatbuffers` crate (`rust/flatbuffers/src/push.rs`), the
`Push` trait provides a default implementation:

```rust
fn alignment() -> PushAlignment {
    PushAlignment::new(align_of::<Self::Output>())
}
```

And `impl_push_for_endian_scalar!` did not override `Push::alignment()`,
inheriting `core::mem::align_of::<T>()` for all primitive scalar types (`bool`,
`u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`, `f32`, `f64`).

On 64-bit targets (`x86_64`, `aarch64`) and 32-bit ARM (`armv7`),
`align_of::<u64>() == 8`, so `align_of::<T>()` happens to equal `size_of::<T>()`.
On 32-bit x86 (`i686`, System V i386 ABI), however, the host ABI alignment of
64-bit scalars (`u64`, `i64`, `f64`) is **4 bytes** (`align_of::<u64>() == 4`),
while their FlatBuffer wire-format size and required wire alignment is **8
bytes** (`size_of::<u64>() == 8`).

As a consequence, on 32-bit x86 (`i686`):
1. `FlatBufferBuilder::push::<u64 / i64 / f64>` only aligns the builder's cursor
   and tracks `min_align` to 4 bytes instead of 8 bytes when writing 64-bit
   table fields or vectors of 64-bit scalars.
2. When a table containing a 64-bit scalar field (`uint64`, `int64`, `double`)
   is serialized on `i686`, the field can be placed at a buffer offset that is
   4-byte aligned but not 8-byte aligned.
3. When the resulting FlatBuffer is verified by C++ `flatbuffers::Verifier`
   (which checks `VerifyField<uint64_t>` with `sizeof(uint64_t) == 8` alignment
   when `FLATBUFFERS_TRACK_VERIFIER_BUFFER_SIZE` / alignment checks are active)
   or transferred to a 64-bit reader, verification fails or unaligned 64-bit
   reads occur.

Fix `impl_push_for_endian_scalar!` to explicitly implement `Push::alignment()`
using `size_of::<$ty>()` so that all endian scalar types always use their
wire-format byte size as their FlatBuffer alignment across all target
architectures.
2026-11-06 15:15:33 -08:00
Raphael Taylor-Davies 374f8fb5fb Rust soundness fixes (#7518)
* Rust soundness fixes

* Second pass

* Make init_from_table unsafe

* Remove SafeSliceAccess

* Clippy

* Remove create_vector_of_strings

* More clippy

* Remove deprecated root type accessors

* More soundness fixes

* Fix EndianScalar for bool

* Add TriviallyTransmutable

* Add debug assertions

* Review comments

* Review feedback
2022-09-29 09:58:49 -04:00
Marcin Witkowski aff818cebf rust: Allow for usage in no_std environment (#6989) 2022-01-20 11:49:02 -05:00
CasperandCasper Neo c24031c36b Mark endian_scalar as unsafe. (#6588)
* Mark endian_scalar as unsafe.

Also
- removed the deprecated flexbuffer slice from example
- fixed some cargo warnings

* Assertions and read_scalar made unsafe

* Clippy lints

* Add to Safety

Co-authored-by: Casper Neo <cneo@google.com>
2021-04-26 09:18:58 -04:00
ImmConCon 187a4787f9 [Rust] Upgrade flatbuffers library to 2018 edition (#6159)
* [Rust] Upgrade flatbuffers lib to 2018 edition

* Pushed version
2020-10-06 15:55:22 -07:00
jean-airoldie db972be264 [rust] Ran rustfmt against library code (#5389) 2019-07-09 13:41:51 -07:00
Robert 3c54fd964b Port FlatBuffers to Rust (#4898)
This is a port of FlatBuffers to Rust. It provides code generation and a
runtime library derived from the C++ implementation. It utilizes the
Rust type system to provide safe and fast traversal of FlatBuffers data.

There are 188 tests, including many fuzz tests of roundtrips for various
serialization scenarios. Initial benchmarks indicate that the canonical
example payload can be written in ~700ns, and traversed in ~100ns.

Rustaceans may be interested in the Follow, Push, and SafeSliceAccess
traits. These traits lift traversals, reads, writes, and slice accesses
into the type system, providing abstraction with no runtime penalty.
2018-09-02 18:26:55 -07:00