Add an optional zerocopy feature deriving byte-conversion traits on wire-format types#190
Open
dflemstr wants to merge 2 commits into
Open
Add an optional zerocopy feature deriving byte-conversion traits on wire-format types#190dflemstr wants to merge 2 commits into
zerocopy feature deriving byte-conversion traits on wire-format types#190dflemstr wants to merge 2 commits into
Conversation
Derives zerocopy's FromBytes, IntoBytes, KnownLayout, and Immutable on a curated allowlist of fixed-layout wire-format types (ZEROCOPY_TYPES in gen/src/main.rs) behind an off-by-default 'zerocopy' feature, so users converting stat/statx/timespec-family structs to and from byte buffers don't need hand-written unsafe or orphan-rule newtype wrappers. The derives verify no-padding/no-pointers per target at compile time, so the allowlist is self-policing: an unsound addition fails the build. CI gains a job checking the feature across a width- and endianness-diverse target set.
Output of gen with the ZEROCOPY_TYPES callback: cfg_attr'd derive lines on the allowlisted wire-format structs, per the architecture exceptions, plus the generated 'zerocopy' feature line. Verified with 'cargo check --features zerocopy' (via -Zbuild-std=core where no prebuilt core exists) for every architecture except csky, m68k, and mips32r6, whose toolchains currently can't build the crate at all (csky) or core itself (m68k SIGSEGV, mips32r6 SIGILL); those three received conservative exceptions.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Programs that pass
stat/statx/timespec-style structs across a byteboundary — sandboxes and supervisors writing into another process's memory,
container runtimes, serializers, anything doing
process_vm_writevorptrace— all end up hand-writing the sameunsafetransmutes-to-bytesaround these types, along with a hand-audited "no padding, no invalid bit
patterns" claim. The zerocopy crate exists to replace exactly that pattern
with compile-time-verified derives, but its traits can't be implemented
downstream (orphan rule), so users today either maintain newtype wrappers or
carry the
unsafethemselves.This adds an off-by-default
zerocopyfeature that derivesFromBytes,IntoBytes,KnownLayout, andImmutableon a curatedallowlist of fixed-layout wire-format types (
ZEROCOPY_TYPESingen/src/main.rs): thestat/statx/statfsfamily,rusage,rlimit/rlimit64, thetimespec/timeval/itimerspecfamily,epoll_event,pollfd,new_utsname, andwinsize.Design notes:
pointers, valid for any bit pattern" per target at compile time, so this
feature adds no
unsafeand no auditing burden here: a type that doesn'tqualify on some architecture fails that architecture's build instead of
compiling into unsoundness. A blanket derive over all generated structs is
not possible for exactly this reason (padded structs like
flock,union-typed fields,
__IncompleteArrayFieldtails), hence the explicitallowlist. The list is easy to extend: add a name, regenerate, and let the
target matrix judge it.
epoll_eventis__EPOLL_PACKEDonly on the x86 family,stathastail padding on powerpc/sparc, x32's
timespecpads after its 32-bittv_nsec, and sparc64'stimevalpads after its 32-bittv_usec.ZEROCOPY_ARCH_EXCEPTIONSomits the derives exactly there (transitively:rusage/itimervalfollow their field types). A missing derive is neverunsound — it's just unavailable on that architecture.
ParseCallbacks::add_attributescallback ingen, as#[cfg_attr(feature = "zerocopy", derive(...))]on struct types in theallowlist, and the
zerocopy = ["dep:zerocopy"]feature line is emittedinto the generated
[features]section. The generated sources in this PRcome from a run of
gen(the diff against the previous generation is theattribute lines only).
zerocopyis optional and off by default withdefault-features = false, features = ["derive"]; nothing changes forexisting users. When enabled it adds one proc-macro dependency chain at
build time and a
#![no_std]-compatible trait crate at runtime.combinations. Enabling
zerocopyrequires zerocopy 0.8's own MSRV(currently 1.65); the new CI job runs on stable only, and the 1.63 leg of
the
checkjob doesn't enable the feature.zerocopyjobcargo checks the feature across a width-and endianness-diverse target set (x86_64 gnu/musl/x32, i686, riscv64,
aarch64, ppc64le, armv5te, loongarch64, s390x), since the padding proof
is per-target. Locally verified with
cargo check --features zerocopy(via
-Zbuild-std=corewhere no prebuilt core exists) on all 20architecture directories except csky (crate doesn't currently build there
at all:
c_charmissing fromctypes, also on main), m68k (rustcSIGSEGV building core), and mips32r6 (rustc SIGILL building core) — those
three carry conservative exceptions.
Happy to adjust the trait set (e.g.
TryFromBytesinstead ofFromBytes),the allowlist, or to gate each trait separately if you'd prefer.