Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement FromBytes and AsBytes for raw pointers #170

Open
2 tasks
joshlf opened this issue May 20, 2023 · 10 comments
Open
2 tasks

Implement FromBytes and AsBytes for raw pointers #170

joshlf opened this issue May 20, 2023 · 10 comments
Labels
compatibility-nonbreaking Changes that are (likely to be) non-breaking

Comments

@joshlf
Copy link
Member

joshlf commented May 20, 2023

Historically, we've avoided adding these impls for fear that they could present a footgun, making it easier to accidentally transmute into a type, breaking its safety invariants.

Today, I was working on replacing some unsafe code in Fuchsia's Starnix project with zerocopy, and ran into some structs for which I can't derive FromBytes or AsBytes because they contain raw pointers. Currently, the lack of impls on raw pointers is entirely preventing this unsafe code from being replaced by zerocopy, which feels to me like throwing the baby out with the bathwater. IMO, it's more important to unlock this use case than to avoid a minor and theoretical footgun.

Note that, while the layout of raw pointers is well-defined, it's less clear that their bit validity is well-defined.

TODO:

@joshlf joshlf added the blocking-next-release This issue should be resolved before we release on crates.io label May 20, 2023
joshlf added a commit that referenced this issue May 20, 2023
Previously, we omitted these impls out of a fear of creating a footgun
in which it would be too easy to mistakenly transmute into a type with
internal safety invariants. Recently, this omission meant that I was
unable to get rid of a number of lines of `unsafe` code in a codebase
that used raw pointers, and it made me realize that it is more important
to enable this use case than to avoid a theoretical footgun.

Closes #170
@joshlf joshlf removed the blocking-next-release This issue should be resolved before we release on crates.io label May 20, 2023
@joshlf
Copy link
Member Author

joshlf commented May 22, 2023

@djkoloski Given the discussion in rust-lang/unsafe-code-guidelines#401, how would you feel about just implementing AsBytes for now and leaving FromBytes for when we've had a deeper discussion about how much of a footgun we're comfortable introducing?

@CAD97
Copy link

CAD97 commented May 22, 2023

I would lean towards treating AsBytes/FromBytes similar to Send/Sync here. Raw pointers on their own don't carry any safe API which would make Send/Sync implementations unsound. Rather, it's that their typical usage is typically not Send/Sync and should consider carefully before implementing those traits.

One could imagine a parallel world where raw pointers were Send/Sync and containers built on them need to contain some PhantomLocal marker to opt out of the autotraits, but that's not the particular tradeoff that was chosen here. Lacking some code required for soundness is also the worst and most subtle kind of soundness bug; typically soundness holes are introduced because of the presence of some impl, not the lack of one, precisely because raw pointers not being Send/Sync makes it difficult to write code reliant on the lack of an autotrait impl for soundness. (And Unpin not being unsafe to implement is often quoted as a footgun due to that exact reason of relying on the lack of an impl for soundness.)

The proof burden/overhead of writing unsafe impl for FromBytes/AsBytes for types holding raw pointers is IMHO appropriate; by doing so the type author is acknowledging the risks involved (e.g. can no longer encapsulate pointer validity).

The calculus is a bit different here since these are opt-in derivable traits rather than autotraits, but I'd say the same logic still applies. It should be fine to just derive all derivable traits without needing to consider whether unsafe elsewhere makes the derive incorrect.

@djkoloski
Copy link
Member

I was under the impression that transmuting pointers to/from bytes was always sound, and that it was just dereferencing transmuted pointers which was unsound. I think that's maybe correct in practice but not entirely correct in theory?

@joshlf Could you point to an example type with pointers that you want to use zerocopy on? I think there is a lot of room for compromise, like a transparent wrapper type or a field attribute with the derive.

@digama0
Copy link

digama0 commented May 22, 2023

I was under the impression that transmuting pointers to/from bytes was always sound, and that it was just dereferencing transmuted pointers which was unsound. I think that's maybe correct in practice but not entirely correct in theory?

As mentioned in the linked issue, this is basically correct, but even if so, the argument @CAD97 is making is that users might make the mistaken assumption (the docs are not clear on whether this is true or not) that transmuting something FromBytes and then back again via AsBytes is a lossless operation, resulting in a pointer which is as good as the original. If not, what is even the point of having the address value?

If you are okay with a wrapper type, I would suggest an ExposedPtr<T> type which is a wrapper around *const T with the invariant that it contains only pointers that have been "exposed" via as-casting to an integer. These can be safely round-tripped through raw bytes without losing their permissions to the original allocation. (In fact, they could just be integers, in which case you don't have to worry about pointer impls at all...)

@joshlf
Copy link
Member Author

joshlf commented May 23, 2023

@joshlf Could you point to an example type with pointers that you want to use zerocopy on? I think there is a lot of room for compromise, like a transparent wrapper type or a field attribute with the derive.

So I think I may have jumped the gun on this one. The original impetus for considering adding these impls was that I was doing a pass through Fuchsia's codebase, looking for mem::transmutes to replace with zerocopy::transmute!. I came across a few transmutes that would have required making a big tree of types FromBytes and AsBytes. In the haze of sifting through thousands of lines of code, I got the impression that there was a lot of code that could benefit from those impls.

However, when I went back now to answer your question, I looked through and found precisely two instances of transmute that could be replaced if only a raw pointer implemented FromBytes or AsBytes. I even made this fancy table because I was expecting to have a lot more data to report:

Trait Type Needed (transitively) by
FromBytes ucontext this transmute (to replace it with transmute!)
AsBytes ucontext this transmute (to replace it with self.as_bytes())

Now, that's only for transmutes, of which there are a few tens in Fuchsia's codebase (ignoring those generated by bindgen, which number in the hundreds). Fuchsia has in the neighborhood of 10,000 instances of unsafe more generally, so it's possible that, going through that code, I'd find a lot more. But right now, all I have to show concretely are those two instances.

For the morbidly curious, here's the full output of rg -g '*.rs' transmute src/:

Output
src/connectivity/lowpan/lib/openthread_rust/src/ot/cli.rs
91:            // Here we must also transmute our closure to have a 'static
98:                self.borrow_backing().cli_output_fn.replace(std::mem::transmute::<

src/connectivity/lowpan/lib/openthread_rust/src/ot/link.rs
268:            // Here we must also transmute our closure to have a 'static lifetime.
272:            self.borrow_backing().active_scan_fn.set(std::mem::transmute::<
324:            // Here we must also transmute our closure to have a 'static lifetime.
328:            self.borrow_backing().energy_scan_fn.set(std::mem::transmute::<

src/connectivity/lowpan/lib/openthread_rust/src/ot/types/ipv6.rs
16:/// be freely and safely transmuted to and from an [`otIp6Address`](crate::otsys::otIp6Address).

src/connectivity/lowpan/lib/openthread_rust/src/ot/types/network_name.rs
50:        use std::mem::transmute;
60:        let slice = unsafe { transmute::<&[u8], &[::std::os::raw::c_char]>(slice) };
76:        use std::mem::transmute;
81:            transmute::<&[::std::os::raw::c_char], &[u8]>(&self.0.m8[0..self.len()])

src/connectivity/lowpan/lib/openthread_rust/src/ot/ip6.rs
289:            // Here we must also transmute our closure to have a 'static lifetime.
293:            self.borrow_backing().ip6_receive_fn.set(std::mem::transmute::<
339:            // Here we must also transmute our closure to have a 'static lifetime.
343:            self.borrow_backing().ip6_address_fn.set(std::mem::transmute::<

src/connectivity/lowpan/lib/openthread_rust/src/ot/srp.rs
674:            // Here we must also transmute our closure to have a 'static lifetime.
678:            self.borrow_backing().srp_server_service_update_fn.set(std::mem::transmute::<

src/connectivity/lowpan/lib/openthread_rust/src/ot/backbone_router.rs
194:            // Here we must also transmute our closure to have a 'static lifetime.
198:            self.borrow_backing().multicast_listener_callback.set(std::mem::transmute::<

src/connectivity/lowpan/lib/openthread_rust/src/ot/dnssd.rs
482:            // Here we must also transmute our closure to have a 'static lifetime.
486:            self.borrow_backing().dnssd_query_sub_unsub_fn.set(std::mem::transmute::<

src/connectivity/lowpan/lib/openthread_rust/src/ot/joiner.rs
196:            // Here we must also transmute our closure to have a 'static lifetime.
200:            self.borrow_backing().joiner_fn.set(std::mem::transmute::<

src/connectivity/lowpan/lib/openthread_sys/src/bindings.rs
1866:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
1871:            let val: u8 = ::std::mem::transmute(val);
1877:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
1882:            let val: u8 = ::std::mem::transmute(val);
1888:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
1893:            let val: u8 = ::std::mem::transmute(val);
1899:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) }
1904:            let val: u8 = ::std::mem::transmute(val);
1910:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
1915:            let val: u8 = ::std::mem::transmute(val);
1929:            let mIsHeaderUpdated: u8 = unsafe { ::std::mem::transmute(mIsHeaderUpdated) };
1933:            let mIsARetx: u8 = unsafe { ::std::mem::transmute(mIsARetx) };
1937:            let mCsmaCaEnabled: u8 = unsafe { ::std::mem::transmute(mCsmaCaEnabled) };
1941:            let mCslPresent: u8 = unsafe { ::std::mem::transmute(mCslPresent) };
1945:            let mIsSecurityProcessed: u8 = unsafe { ::std::mem::transmute(mIsSecurityProcessed) };
1974:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
1979:            let val: u8 = ::std::mem::transmute(val);
1985:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
1990:            let val: u8 = ::std::mem::transmute(val);
2002:                unsafe { ::std::mem::transmute(mAckedWithFramePending) };
2006:            let mAckedWithSecEnhAck: u8 = unsafe { ::std::mem::transmute(mAckedWithSecEnhAck) };
2092:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
2097:            let val: u8 = ::std::mem::transmute(val);
2103:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
2108:            let val: u8 = ::std::mem::transmute(val);
2114:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
2119:            let val: u8 = ::std::mem::transmute(val);
2125:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) }
2130:            let val: u8 = ::std::mem::transmute(val);
2136:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
2141:            let val: u8 = ::std::mem::transmute(val);
2155:            let mPduCount: u8 = unsafe { ::std::mem::transmute(mPduCount) };
2159:            let mLqi: u8 = unsafe { ::std::mem::transmute(mLqi) };
2163:            let mLinkMargin: u8 = unsafe { ::std::mem::transmute(mLinkMargin) };
2167:            let mRssi: u8 = unsafe { ::std::mem::transmute(mRssi) };
2171:            let mReserved: u8 = unsafe { ::std::mem::transmute(mReserved) };
3178:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
3183:            let val: u8 = ::std::mem::transmute(val);
3189:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
3194:            let val: u8 = ::std::mem::transmute(val);
3200:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
3205:            let val: u8 = ::std::mem::transmute(val);
3211:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 4u8) as u32) }
3216:            let val: u32 = ::std::mem::transmute(val);
3222:        unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u8) }
3227:            let val: u8 = ::std::mem::transmute(val);
3241:            let mPreferred: u8 = unsafe { ::std::mem::transmute(mPreferred) };
3245:            let mValid: u8 = unsafe { ::std::mem::transmute(mValid) };
3249:            let mScopeOverrideValid: u8 = unsafe { ::std::mem::transmute(mScopeOverrideValid) };
3253:            let mScopeOverride: u32 = unsafe { ::std::mem::transmute(mScopeOverride) };
3257:            let mRloc: u8 = unsafe { ::std::mem::transmute(mRloc) };
3347:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 2u8) as u8) }
3352:            let val: u8 = ::std::mem::transmute(val);
3358:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
3363:            let val: u8 = ::std::mem::transmute(val);
3369:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) }
3374:            let val: u8 = ::std::mem::transmute(val);
3380:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
3385:            let val: u8 = ::std::mem::transmute(val);
3398:            let mEcn: u8 = unsafe { ::std::mem::transmute(mEcn) };
3402:            let mIsHostInterface: u8 = unsafe { ::std::mem::transmute(mIsHostInterface) };
3406:            let mAllowZeroHopLimit: u8 = unsafe { ::std::mem::transmute(mAllowZeroHopLimit) };
3410:            let mMulticastLoop: u8 = unsafe { ::std::mem::transmute(mMulticastLoop) };
3663:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) }
3668:            let val: u8 = ::std::mem::transmute(val);
3674:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
3679:            let val: u8 = ::std::mem::transmute(val);
3687:            let mScope: u8 = unsafe { ::std::mem::transmute(mScope) };
3691:            let mPreferred: u8 = unsafe { ::std::mem::transmute(mPreferred) };
4166:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 2u8) as u32) }
4171:            let val: u32 = ::std::mem::transmute(val);
4177:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
4182:            let val: u8 = ::std::mem::transmute(val);
4188:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) }
4193:            let val: u8 = ::std::mem::transmute(val);
4199:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
4204:            let val: u8 = ::std::mem::transmute(val);
4210:        unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u8) }
4215:            let val: u8 = ::std::mem::transmute(val);
4221:        unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u8) }
4226:            let val: u8 = ::std::mem::transmute(val);
4232:        unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u8) }
4237:            let val: u8 = ::std::mem::transmute(val);
4243:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u8) }
4248:            let val: u8 = ::std::mem::transmute(val);
4254:        unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u8) }
4259:            let val: u8 = ::std::mem::transmute(val);
4265:        unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u8) }
4270:            let val: u8 = ::std::mem::transmute(val);
4289:            let mPreference: u32 = unsafe { ::std::mem::transmute(mPreference) };
4293:            let mPreferred: u8 = unsafe { ::std::mem::transmute(mPreferred) };
4297:            let mSlaac: u8 = unsafe { ::std::mem::transmute(mSlaac) };
4301:            let mDhcp: u8 = unsafe { ::std::mem::transmute(mDhcp) };
4305:            let mConfigure: u8 = unsafe { ::std::mem::transmute(mConfigure) };
4309:            let mDefaultRoute: u8 = unsafe { ::std::mem::transmute(mDefaultRoute) };
4313:            let mOnMesh: u8 = unsafe { ::std::mem::transmute(mOnMesh) };
4317:            let mStable: u8 = unsafe { ::std::mem::transmute(mStable) };
4321:            let mNdDns: u8 = unsafe { ::std::mem::transmute(mNdDns) };
4325:            let mDp: u8 = unsafe { ::std::mem::transmute(mDp) };
4378:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 2u8) as u32) }
4383:            let val: u32 = ::std::mem::transmute(val);
4389:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
4394:            let val: u8 = ::std::mem::transmute(val);
4400:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) }
4405:            let val: u8 = ::std::mem::transmute(val);
4411:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
4416:            let val: u8 = ::std::mem::transmute(val);
4429:            let mPreference: u32 = unsafe { ::std::mem::transmute(mPreference) };
4433:            let mNat64: u8 = unsafe { ::std::mem::transmute(mNat64) };
4437:            let mStable: u8 = unsafe { ::std::mem::transmute(mStable) };
4441:            let mNextHopIsThisDevice: u8 = unsafe { ::std::mem::transmute(mNextHopIsThisDevice) };
4482:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
4487:            let val: u8 = ::std::mem::transmute(val);
4495:            let mStable: u8 = unsafe { ::std::mem::transmute(mStable) };
7312:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
7317:            let val: u8 = ::std::mem::transmute(val);
7323:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
7328:            let val: u8 = ::std::mem::transmute(val);
7334:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
7339:            let val: u8 = ::std::mem::transmute(val);
7345:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) }
7350:            let val: u8 = ::std::mem::transmute(val);
7356:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
7361:            let val: u8 = ::std::mem::transmute(val);
7367:        unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u8) }
7372:            let val: u8 = ::std::mem::transmute(val);
7378:        unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u8) }
7383:            let val: u8 = ::std::mem::transmute(val);
7389:        unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u8) }
7394:            let val: u8 = ::std::mem::transmute(val);
7400:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u8) }
7405:            let val: u8 = ::std::mem::transmute(val);
7411:        unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 3u8) as u8) }
7416:            let val: u8 = ::std::mem::transmute(val);
7436:                unsafe { ::std::mem::transmute(mObtainNetworkKeyEnabled) };
7441:                unsafe { ::std::mem::transmute(mNativeCommissioningEnabled) };
7445:            let mRoutersEnabled: u8 = unsafe { ::std::mem::transmute(mRoutersEnabled) };
7450:                unsafe { ::std::mem::transmute(mExternalCommissioningEnabled) };
7455:                unsafe { ::std::mem::transmute(mCommercialCommissioningEnabled) };
7460:                unsafe { ::std::mem::transmute(mAutonomousEnrollmentEnabled) };
7465:                unsafe { ::std::mem::transmute(mNetworkKeyProvisioningEnabled) };
7469:            let mTobleLinkEnabled: u8 = unsafe { ::std::mem::transmute(mTobleLinkEnabled) };
7473:            let mNonCcmRoutersEnabled: u8 = unsafe { ::std::mem::transmute(mNonCcmRoutersEnabled) };
7478:                unsafe { ::std::mem::transmute(mVersionThresholdForRouting) };
7498:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
7503:            let val: u8 = ::std::mem::transmute(val);
7509:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
7514:            let val: u8 = ::std::mem::transmute(val);
7520:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
7525:            let val: u8 = ::std::mem::transmute(val);
7531:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) }
7536:            let val: u8 = ::std::mem::transmute(val);
7542:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
7547:            let val: u8 = ::std::mem::transmute(val);
7553:        unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u8) }
7558:            let val: u8 = ::std::mem::transmute(val);
7564:        unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u8) }
7569:            let val: u8 = ::std::mem::transmute(val);
7575:        unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u8) }
7580:            let val: u8 = ::std::mem::transmute(val);
7586:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u8) }
7591:            let val: u8 = ::std::mem::transmute(val);
7597:        unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u8) }
7602:            let val: u8 = ::std::mem::transmute(val);
7608:        unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u8) }
7613:            let val: u8 = ::std::mem::transmute(val);
7619:        unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 1u8) as u8) }
7624:            let val: u8 = ::std::mem::transmute(val);
7646:                unsafe { ::std::mem::transmute(mIsActiveTimestampPresent) };
7651:                unsafe { ::std::mem::transmute(mIsPendingTimestampPresent) };
7655:            let mIsNetworkKeyPresent: u8 = unsafe { ::std::mem::transmute(mIsNetworkKeyPresent) };
7659:            let mIsNetworkNamePresent: u8 = unsafe { ::std::mem::transmute(mIsNetworkNamePresent) };
7664:                unsafe { ::std::mem::transmute(mIsExtendedPanIdPresent) };
7669:                unsafe { ::std::mem::transmute(mIsMeshLocalPrefixPresent) };
7673:            let mIsDelayPresent: u8 = unsafe { ::std::mem::transmute(mIsDelayPresent) };
7677:            let mIsPanIdPresent: u8 = unsafe { ::std::mem::transmute(mIsPanIdPresent) };
7681:            let mIsChannelPresent: u8 = unsafe { ::std::mem::transmute(mIsChannelPresent) };
7685:            let mIsPskcPresent: u8 = unsafe { ::std::mem::transmute(mIsPskcPresent) };
7690:                unsafe { ::std::mem::transmute(mIsSecurityPolicyPresent) };
7694:            let mIsChannelMaskPresent: u8 = unsafe { ::std::mem::transmute(mIsChannelMaskPresent) };
8359:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
8364:            let val: u8 = ::std::mem::transmute(val);
8370:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
8375:            let val: u8 = ::std::mem::transmute(val);
8381:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
8386:            let val: u8 = ::std::mem::transmute(val);
8392:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) }
8397:            let val: u8 = ::std::mem::transmute(val);
8410:            let mIsLocatorSet: u8 = unsafe { ::std::mem::transmute(mIsLocatorSet) };
8414:            let mIsSessionIdSet: u8 = unsafe { ::std::mem::transmute(mIsSessionIdSet) };
8418:            let mIsSteeringDataSet: u8 = unsafe { ::std::mem::transmute(mIsSteeringDataSet) };
8422:            let mIsJoinerUdpPortSet: u8 = unsafe { ::std::mem::transmute(mIsJoinerUdpPortSet) };
10305:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
10310:            let val: u8 = ::std::mem::transmute(val);
10316:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
10321:            let val: u8 = ::std::mem::transmute(val);
10332:            let mLinkSecurity: u8 = unsafe { ::std::mem::transmute(mLinkSecurity) };
10336:            let mIsDstPanIdBroadcast: u8 = unsafe { ::std::mem::transmute(mIsDstPanIdBroadcast) };
10557:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u32) }
10562:            let val: u32 = ::std::mem::transmute(val);
10568:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
10573:            let val: u8 = ::std::mem::transmute(val);
10579:        unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u8) }
10584:            let val: u8 = ::std::mem::transmute(val);
10590:        unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u8) }
10595:            let val: u8 = ::std::mem::transmute(val);
10608:            let mVersion: u32 = unsafe { ::std::mem::transmute(mVersion) };
10612:            let mIsNative: u8 = unsafe { ::std::mem::transmute(mIsNative) };
10616:            let mDiscover: u8 = unsafe { ::std::mem::transmute(mDiscover) };
10620:            let mIsJoinable: u8 = unsafe { ::std::mem::transmute(mIsJoinable) };
11885:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
11890:            let val: u8 = ::std::mem::transmute(val);
11896:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
11901:            let val: u8 = ::std::mem::transmute(val);
11912:            let mSupportsIeee802154: u8 = unsafe { ::std::mem::transmute(mSupportsIeee802154) };
11916:            let mSupportsTrelUdp6: u8 = unsafe { ::std::mem::transmute(mSupportsTrelUdp6) };
12539:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
12544:            let val: u8 = ::std::mem::transmute(val);
12550:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
12555:            let val: u8 = ::std::mem::transmute(val);
12561:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
12566:            let val: u8 = ::std::mem::transmute(val);
12578:            let mRxOnWhenIdle: u8 = unsafe { ::std::mem::transmute(mRxOnWhenIdle) };
12582:            let mDeviceType: u8 = unsafe { ::std::mem::transmute(mDeviceType) };
12586:            let mNetworkData: u8 = unsafe { ::std::mem::transmute(mNetworkData) };
12628:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
12633:            let val: u8 = ::std::mem::transmute(val);
12639:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
12644:            let val: u8 = ::std::mem::transmute(val);
12650:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
12655:            let val: u8 = ::std::mem::transmute(val);
12661:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) }
12666:            let val: u8 = ::std::mem::transmute(val);
12679:            let mRxOnWhenIdle: u8 = unsafe { ::std::mem::transmute(mRxOnWhenIdle) };
12683:            let mFullThreadDevice: u8 = unsafe { ::std::mem::transmute(mFullThreadDevice) };
12687:            let mFullNetworkData: u8 = unsafe { ::std::mem::transmute(mFullNetworkData) };
12691:            let mIsChild: u8 = unsafe { ::std::mem::transmute(mIsChild) };
12747:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
12752:            let val: u8 = ::std::mem::transmute(val);
12758:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
12763:            let val: u8 = ::std::mem::transmute(val);
12774:            let mAllocated: u8 = unsafe { ::std::mem::transmute(mAllocated) };
12778:            let mLinkEstablished: u8 = unsafe { ::std::mem::transmute(mLinkEstablished) };
13591:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) }
13596:            let val: u8 = ::std::mem::transmute(val);
13602:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
13607:            let val: u8 = ::std::mem::transmute(val);
13615:            let mVersion: u8 = unsafe { ::std::mem::transmute(mVersion) };
13619:            let mIsJoiner: u8 = unsafe { ::std::mem::transmute(mIsJoiner) };
13830:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 2u8) as u8) }
13835:            let val: u8 = ::std::mem::transmute(val);
13841:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 2u8) as u8) }
13846:            let val: u8 = ::std::mem::transmute(val);
13852:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u8) }
13857:            let val: u8 = ::std::mem::transmute(val);
13869:            let mLinkQualityOut: u8 = unsafe { ::std::mem::transmute(mLinkQualityOut) };
13873:            let mLinkQualityIn: u8 = unsafe { ::std::mem::transmute(mLinkQualityIn) };
13877:            let mRouteCost: u8 = unsafe { ::std::mem::transmute(mRouteCost) };
13935:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 5u8) as u16) }
13940:            let val: u16 = ::std::mem::transmute(val);
13946:        unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 2u8) as u8) }
13951:            let val: u8 = ::std::mem::transmute(val);
13957:        unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 9u8) as u16) }
13962:            let val: u16 = ::std::mem::transmute(val);
13974:            let mTimeout: u16 = unsafe { ::std::mem::transmute(mTimeout) };
13978:            let mLinkQuality: u8 = unsafe { ::std::mem::transmute(mLinkQuality) };
13982:            let mChildId: u16 = unsafe { ::std::mem::transmute(mChildId) };
18606:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
18611:            let val: u8 = ::std::mem::transmute(val);
18617:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
18622:            let val: u8 = ::std::mem::transmute(val);
18628:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
18633:            let val: u8 = ::std::mem::transmute(val);
18639:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u8) }
18644:            let val: u8 = ::std::mem::transmute(val);
18650:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u8) }
18655:            let val: u8 = ::std::mem::transmute(val);
18669:            let mRxOnWhenIdle: u8 = unsafe { ::std::mem::transmute(mRxOnWhenIdle) };
18673:            let mFullThreadDevice: u8 = unsafe { ::std::mem::transmute(mFullThreadDevice) };
18677:            let mFullNetworkData: u8 = unsafe { ::std::mem::transmute(mFullNetworkData) };
18681:            let mIsStateRestoring: u8 = unsafe { ::std::mem::transmute(mIsStateRestoring) };
18685:            let mIsCslSynced: u8 = unsafe { ::std::mem::transmute(mIsCslSynced) };
18733:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
18738:            let val: u8 = ::std::mem::transmute(val);
18744:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
18749:            let val: u8 = ::std::mem::transmute(val);
18760:            let mCanEvict: u8 = unsafe { ::std::mem::transmute(mCanEvict) };
18764:            let mValidLastTrans: u8 = unsafe { ::std::mem::transmute(mValidLastTrans) };
18905:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u8) }
18910:            let val: u8 = ::std::mem::transmute(val);
18916:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u8) }
18921:            let val: u8 = ::std::mem::transmute(val);
18927:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u8) }
18932:            let val: u8 = ::std::mem::transmute(val);
18944:            let mIsBorderRouter: u8 = unsafe { ::std::mem::transmute(mIsBorderRouter) };
18948:            let mSupportsCcm: u8 = unsafe { ::std::mem::transmute(mSupportsCcm) };
18952:            let mIsUnstable: u8 = unsafe { ::std::mem::transmute(mIsUnstable) };

src/connectivity/lib/net-types/src/ip.rs
1574:            zerocopy::transmute!(self.ipv6_bytes());

src/connectivity/lib/network-device/rust/src/session/buffer/pool.rs
518:        // to transmute and swap the values between the storages. After the swap
522:            std::mem::transmute(&mut tx.descs.storage)
539:        unsafe { std::mem::transmute(&self.storage[..self.len.into()]) }
546:        unsafe { std::mem::transmute(&mut self.storage[..self.len.into()]) }
657:            std::ptr::drop_in_place(std::mem::transmute::<_, &mut [T]>(

src/storage/fuchsia-fatfs/src/refs.rs
28:        FatfsDirRef { inner: Some(std::mem::transmute(dir)), open_count: 1 }
38:        unsafe { std::mem::transmute(self.inner.as_ref()) }
44:        // We need to transmute() back to the right lifetime because otherwise rust forces us to
48:        unsafe { std::mem::transmute(self.inner.as_mut()) }
78:        self.inner.replace(std::mem::transmute(dir));
112:        unsafe { std::mem::transmute(self.inner.take()) }
137:        FatfsFileRef { inner: Some(std::mem::transmute(file)), open_count: 1 }
143:        // We need to transmute() back to the right lifetime because otherwise rust forces us to
147:        unsafe { std::mem::transmute(self.inner.as_mut()) }
177:        self.inner.replace(std::mem::transmute(file));

src/storage/flashmap/src/flashmap.rs
241:            let header: &FlashmapHeader = unsafe { std::mem::transmute(&data[i]) };
304:        let header: &FlashmapHeader = unsafe { std::mem::transmute(&data[offset_in_vmar]) };
312:        let areas_ptr: *const RawFlashmapArea = unsafe { std::mem::transmute(&data[area_start]) };

src/starnix/kernel/arch/x64/signal_handling.rs
105:        unsafe { std::mem::transmute(self) }
109:        unsafe { std::mem::transmute(bytes) }

src/starnix/kernel/arch/aarch64/signal_handling.rs
113:        unsafe { std::mem::transmute(self) }
117:        unsafe { std::mem::transmute(bytes) }

src/starnix/kernel/execution/shared.rs
327:    zerocopy::transmute!(tmp)

src/storage/fxfs/src/data_buffer.rs
729:    // pointer rather than a reference so that we don't have to transmute away the lifetimes when we

src/starnix/lib/linux_uapi/src/arm64.rs
5118:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) }
5123:            let val: u8 = ::std::mem::transmute(val);
5129:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u8) }
5134:            let val: u8 = ::std::mem::transmute(val);
5142:            let dst_reg: u8 = unsafe { ::std::mem::transmute(dst_reg) };
5146:            let src_reg: u8 = unsafe { ::std::mem::transmute(src_reg) };
6761:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
6766:            let val: u32 = ::std::mem::transmute(val);
6774:            let gpl_compatible: u32 = unsafe { ::std::mem::transmute(gpl_compatible) };
9141:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) }
9146:            let val: u8 = ::std::mem::transmute(val);
9152:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u8) }
9157:            let val: u8 = ::std::mem::transmute(val);
9165:            let ihl: u8 = unsafe { ::std::mem::transmute(ihl) };
9169:            let version: u8 = unsafe { ::std::mem::transmute(version) };
9501:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) }
9506:            let val: u8 = ::std::mem::transmute(val);
9512:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u8) }
9517:            let val: u8 = ::std::mem::transmute(val);
9525:            let priority: u8 = unsafe { ::std::mem::transmute(priority) };
9529:            let version: u8 = unsafe { ::std::mem::transmute(version) };

src/starnix/lib/linux_uapi/src/x86_64.rs
5421:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) }
5426:            let val: u8 = ::std::mem::transmute(val);
5432:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u8) }
5437:            let val: u8 = ::std::mem::transmute(val);
5445:            let dst_reg: u8 = unsafe { ::std::mem::transmute(dst_reg) };
5449:            let src_reg: u8 = unsafe { ::std::mem::transmute(src_reg) };
7064:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
7069:            let val: u32 = ::std::mem::transmute(val);
7077:            let gpl_compatible: u32 = unsafe { ::std::mem::transmute(gpl_compatible) };
9390:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) }
9395:            let val: u8 = ::std::mem::transmute(val);
9401:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u8) }
9406:            let val: u8 = ::std::mem::transmute(val);
9414:            let ihl: u8 = unsafe { ::std::mem::transmute(ihl) };
9418:            let version: u8 = unsafe { ::std::mem::transmute(version) };
9750:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 4u8) as u8) }
9755:            let val: u8 = ::std::mem::transmute(val);
9761:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 4u8) as u8) }
9766:            let val: u8 = ::std::mem::transmute(val);
9774:            let priority: u8 = unsafe { ::std::mem::transmute(priority) };
9778:            let version: u8 = unsafe { ::std::mem::transmute(version) };

src/developer/ssh-key-manager/src/manager.rs
425:            unsafe { std::mem::transmute(file.get_mut()) };

src/developer/ffx/plugins/emulator/common/src/tuntap.rs
326:            .returning(|| Ok(unsafe { std::mem::transmute(TestInterfaceAddressIterator::new()) }));

src/graphics/lib/compute/surpass/src/painter/mod.rs
207:        unsafe { mem::transmute(&mut self.covers) }
274:            unsafe { mem::transmute(&mut self.doubled_areas) };
276:            unsafe { mem::transmute(&mut self.covers) };

src/graphics/lib/compute/surpass/src/simd/avx.rs
123:        unsafe { std::mem::transmute(&mut self.0) }
301:        zerocopy::transmute!(self.0)
405:        zerocopy::transmute!(self.0)

src/graphics/lib/compute/surpass/src/simd/wasm32.rs
142:        zerocopy::transmute!(self.0)
165:        std::mem::transmute(&mut self.0)
389:        zerocopy::transmute!(self.0)

src/graphics/lib/compute/surpass/src/simd/aarch64.rs
139:        zerocopy::transmute!(self.0)
161:        unsafe { std::mem::transmute(&mut self.0) }
384:        zerocopy::transmute!(self.0)

src/graphics/lib/compute/surpass/src/layout/slice_cache.rs
308:        Self { len, slices: unsafe { mem::transmute(f(span)) } }
352:            // Generic `Slice<'static, ()>` are transmuted to `Slice<'s, T>`, enforcing the
355:            return Some(unsafe { mem::transmute(&mut *self.slices) });
371:            // Generic `Slice<'static, ()>` are transmuted to `Slice<'s, T>`, enforcing the
374:            return Some(unsafe { mem::transmute(&mut *self.slices) });

src/lib/usb_rs/src/usb_osx/iokit_usb.rs
5547:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) }
5552:            let val: u16 = ::std::mem::transmute(val);
5558:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) }
5563:            let val: u16 = ::std::mem::transmute(val);
5569:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) }
5574:            let val: u16 = ::std::mem::transmute(val);
5580:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u16) }
5585:            let val: u16 = ::std::mem::transmute(val);
5591:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u16) }
5596:            let val: u16 = ::std::mem::transmute(val);
5602:        unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u16) }
5607:            let val: u16 = ::std::mem::transmute(val);
5613:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 2u8) as u16) }
5618:            let val: u16 = ::std::mem::transmute(val);
5624:        unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 2u8) as u16) }
5629:            let val: u16 = ::std::mem::transmute(val);
5646:            let __invalid: u16 = unsafe { ::std::mem::transmute(__invalid) };
5650:            let __denorm: u16 = unsafe { ::std::mem::transmute(__denorm) };
5654:            let __zdiv: u16 = unsafe { ::std::mem::transmute(__zdiv) };
5658:            let __ovrfl: u16 = unsafe { ::std::mem::transmute(__ovrfl) };
5662:            let __undfl: u16 = unsafe { ::std::mem::transmute(__undfl) };
5666:            let __precis: u16 = unsafe { ::std::mem::transmute(__precis) };
5670:            let __pc: u16 = unsafe { ::std::mem::transmute(__pc) };
5674:            let __rc: u16 = unsafe { ::std::mem::transmute(__rc) };
5704:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u16) }
5709:            let val: u16 = ::std::mem::transmute(val);
5715:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u16) }
5720:            let val: u16 = ::std::mem::transmute(val);
5726:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u16) }
5731:            let val: u16 = ::std::mem::transmute(val);
5737:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 1u8) as u16) }
5742:            let val: u16 = ::std::mem::transmute(val);
5748:        unsafe { ::std::mem::transmute(self._bitfield_1.get(4usize, 1u8) as u16) }
5753:            let val: u16 = ::std::mem::transmute(val);
5759:        unsafe { ::std::mem::transmute(self._bitfield_1.get(5usize, 1u8) as u16) }
5764:            let val: u16 = ::std::mem::transmute(val);
5770:        unsafe { ::std::mem::transmute(self._bitfield_1.get(6usize, 1u8) as u16) }
5775:            let val: u16 = ::std::mem::transmute(val);
5781:        unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u16) }
5786:            let val: u16 = ::std::mem::transmute(val);
5792:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 1u8) as u16) }
5797:            let val: u16 = ::std::mem::transmute(val);
5803:        unsafe { ::std::mem::transmute(self._bitfield_1.get(9usize, 1u8) as u16) }
5808:            let val: u16 = ::std::mem::transmute(val);
5814:        unsafe { ::std::mem::transmute(self._bitfield_1.get(10usize, 1u8) as u16) }
5819:            let val: u16 = ::std::mem::transmute(val);
5825:        unsafe { ::std::mem::transmute(self._bitfield_1.get(11usize, 3u8) as u16) }
5830:            let val: u16 = ::std::mem::transmute(val);
5836:        unsafe { ::std::mem::transmute(self._bitfield_1.get(14usize, 1u8) as u16) }
5841:            let val: u16 = ::std::mem::transmute(val);
5847:        unsafe { ::std::mem::transmute(self._bitfield_1.get(15usize, 1u8) as u16) }
5852:            let val: u16 = ::std::mem::transmute(val);
5875:            let __invalid: u16 = unsafe { ::std::mem::transmute(__invalid) };
5879:            let __denorm: u16 = unsafe { ::std::mem::transmute(__denorm) };
5883:            let __zdiv: u16 = unsafe { ::std::mem::transmute(__zdiv) };
5887:            let __ovrfl: u16 = unsafe { ::std::mem::transmute(__ovrfl) };
5891:            let __undfl: u16 = unsafe { ::std::mem::transmute(__undfl) };
5895:            let __precis: u16 = unsafe { ::std::mem::transmute(__precis) };
5899:            let __stkflt: u16 = unsafe { ::std::mem::transmute(__stkflt) };
5903:            let __errsumm: u16 = unsafe { ::std::mem::transmute(__errsumm) };
5907:            let __c0: u16 = unsafe { ::std::mem::transmute(__c0) };
5911:            let __c1: u16 = unsafe { ::std::mem::transmute(__c1) };
5915:            let __c2: u16 = unsafe { ::std::mem::transmute(__c2) };
5919:            let __tos: u16 = unsafe { ::std::mem::transmute(__tos) };
5923:            let __c3: u16 = unsafe { ::std::mem::transmute(__c3) };
5927:            let __busy: u16 = unsafe { ::std::mem::transmute(__busy) };
7889:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
7894:            let val: u32 = ::std::mem::transmute(val);
7900:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) }
7905:            let val: u32 = ::std::mem::transmute(val);
7911:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 1u8) as u32) }
7916:            let val: u32 = ::std::mem::transmute(val);
7922:        unsafe { ::std::mem::transmute(self._bitfield_1.get(3usize, 16u8) as u32) }
7927:            let val: u32 = ::std::mem::transmute(val);
7933:        unsafe { ::std::mem::transmute(self._bitfield_1.get(19usize, 13u8) as u32) }
7938:            let val: u32 = ::std::mem::transmute(val);
7952:            let __mispredict: u32 = unsafe { ::std::mem::transmute(__mispredict) };
7956:            let __tsx_abort: u32 = unsafe { ::std::mem::transmute(__tsx_abort) };
7960:            let __in_tsx: u32 = unsafe { ::std::mem::transmute(__in_tsx) };
7964:            let __cycle_count: u32 = unsafe { ::std::mem::transmute(__cycle_count) };
7968:            let __reserved: u32 = unsafe { ::std::mem::transmute(__reserved) };
8015:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
8020:            let val: u32 = ::std::mem::transmute(val);
8026:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) }
8031:            let val: u32 = ::std::mem::transmute(val);
8037:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 30u8) as u32) }
8042:            let val: u32 = ::std::mem::transmute(val);
8054:            let __lbr_supported_tsx: u32 = unsafe { ::std::mem::transmute(__lbr_supported_tsx) };
8059:                unsafe { ::std::mem::transmute(__lbr_supported_cycle_count) };
8063:            let __reserved: u32 = unsafe { ::std::mem::transmute(__reserved) };
15051:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 7u8) as u32) }
15056:            let val: u32 = ::std::mem::transmute(val);
15062:        unsafe { ::std::mem::transmute(self._bitfield_1.get(7usize, 1u8) as u32) }
15067:            let val: u32 = ::std::mem::transmute(val);
15073:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u32) }
15078:            let val: u32 = ::std::mem::transmute(val);
15084:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 16u8) as u32) }
15089:            let val: u32 = ::std::mem::transmute(val);
15102:            let w_Termsig: u32 = unsafe { ::std::mem::transmute(w_Termsig) };
15106:            let w_Coredump: u32 = unsafe { ::std::mem::transmute(w_Coredump) };
15110:            let w_Retcode: u32 = unsafe { ::std::mem::transmute(w_Retcode) };
15114:            let w_Filler: u32 = unsafe { ::std::mem::transmute(w_Filler) };
15143:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 8u8) as u32) }
15148:            let val: u32 = ::std::mem::transmute(val);
15154:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u32) }
15159:            let val: u32 = ::std::mem::transmute(val);
15165:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 16u8) as u32) }
15170:            let val: u32 = ::std::mem::transmute(val);
15182:            let w_Stopval: u32 = unsafe { ::std::mem::transmute(w_Stopval) };
15186:            let w_Stopsig: u32 = unsafe { ::std::mem::transmute(w_Stopsig) };
15190:            let w_Filler: u32 = unsafe { ::std::mem::transmute(w_Filler) };
22240:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 1u8) as u32) }
22245:            let val: u32 = ::std::mem::transmute(val);
22251:        unsafe { ::std::mem::transmute(self._bitfield_1.get(1usize, 1u8) as u32) }
22256:            let val: u32 = ::std::mem::transmute(val);
22262:        unsafe { ::std::mem::transmute(self._bitfield_1.get(2usize, 30u8) as u32) }
22267:            let val: u32 = ::std::mem::transmute(val);
22279:            let name: u32 = unsafe { ::std::mem::transmute(name) };
22283:            let prealloc: u32 = unsafe { ::std::mem::transmute(prealloc) };
22287:            let pad1: u32 = unsafe { ::std::mem::transmute(pad1) };
25877:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 24u8) as u32) }
25882:            let val: u32 = ::std::mem::transmute(val);
25888:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
25893:            let val: u32 = ::std::mem::transmute(val);
25904:            let pad3: u32 = unsafe { ::std::mem::transmute(pad3) };
25908:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };
25961:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 16u8) as u32) }
25966:            let val: u32 = ::std::mem::transmute(val);
25972:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u32) }
25977:            let val: u32 = ::std::mem::transmute(val);
25983:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
25988:            let val: u32 = ::std::mem::transmute(val);
26000:            let pad2: u32 = unsafe { ::std::mem::transmute(pad2) };
26004:            let disposition: u32 = unsafe { ::std::mem::transmute(disposition) };
26008:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };
26061:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 8u8) as u32) }
26066:            let val: u32 = ::std::mem::transmute(val);
26072:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u32) }
26077:            let val: u32 = ::std::mem::transmute(val);
26083:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u32) }
26088:            let val: u32 = ::std::mem::transmute(val);
26094:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
26099:            let val: u32 = ::std::mem::transmute(val);
26112:            let deallocate: u32 = unsafe { ::std::mem::transmute(deallocate) };
26116:            let copy: u32 = unsafe { ::std::mem::transmute(copy) };
26120:            let pad1: u32 = unsafe { ::std::mem::transmute(pad1) };
26124:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };
26177:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 8u8) as u32) }
26182:            let val: u32 = ::std::mem::transmute(val);
26188:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u32) }
26193:            let val: u32 = ::std::mem::transmute(val);
26199:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u32) }
26204:            let val: u32 = ::std::mem::transmute(val);
26210:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
26215:            let val: u32 = ::std::mem::transmute(val);
26228:            let deallocate: u32 = unsafe { ::std::mem::transmute(deallocate) };
26232:            let copy: u32 = unsafe { ::std::mem::transmute(copy) };
26236:            let pad1: u32 = unsafe { ::std::mem::transmute(pad1) };
26240:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };
26297:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 8u8) as u32) }
26302:            let val: u32 = ::std::mem::transmute(val);
26308:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u32) }
26313:            let val: u32 = ::std::mem::transmute(val);
26319:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u32) }
26324:            let val: u32 = ::std::mem::transmute(val);
26330:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
26335:            let val: u32 = ::std::mem::transmute(val);
26348:            let deallocate: u32 = unsafe { ::std::mem::transmute(deallocate) };
26352:            let copy: u32 = unsafe { ::std::mem::transmute(copy) };
26356:            let pad1: u32 = unsafe { ::std::mem::transmute(pad1) };
26360:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };
26413:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 8u8) as u32) }
26418:            let val: u32 = ::std::mem::transmute(val);
26424:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u32) }
26429:            let val: u32 = ::std::mem::transmute(val);
26435:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u32) }
26440:            let val: u32 = ::std::mem::transmute(val);
26446:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
26451:            let val: u32 = ::std::mem::transmute(val);
26464:            let deallocate: u32 = unsafe { ::std::mem::transmute(deallocate) };
26468:            let copy: u32 = unsafe { ::std::mem::transmute(copy) };
26472:            let disposition: u32 = unsafe { ::std::mem::transmute(disposition) };
26476:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };
26529:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 8u8) as u32) }
26534:            let val: u32 = ::std::mem::transmute(val);
26540:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u32) }
26545:            let val: u32 = ::std::mem::transmute(val);
26551:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u32) }
26556:            let val: u32 = ::std::mem::transmute(val);
26562:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
26567:            let val: u32 = ::std::mem::transmute(val);
26580:            let deallocate: u32 = unsafe { ::std::mem::transmute(deallocate) };
26584:            let copy: u32 = unsafe { ::std::mem::transmute(copy) };
26588:            let disposition: u32 = unsafe { ::std::mem::transmute(disposition) };
26592:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };
26654:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 8u8) as u32) }
26659:            let val: u32 = ::std::mem::transmute(val);
26665:        unsafe { ::std::mem::transmute(self._bitfield_1.get(8usize, 8u8) as u32) }
26670:            let val: u32 = ::std::mem::transmute(val);
26676:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u32) }
26681:            let val: u32 = ::std::mem::transmute(val);
26687:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
26692:            let val: u32 = ::std::mem::transmute(val);
26705:            let deallocate: u32 = unsafe { ::std::mem::transmute(deallocate) };
26709:            let copy: u32 = unsafe { ::std::mem::transmute(copy) };
26713:            let disposition: u32 = unsafe { ::std::mem::transmute(disposition) };
26717:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };
26770:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 16u8) as u32) }
26775:            let val: u32 = ::std::mem::transmute(val);
26781:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u32) }
26786:            let val: u32 = ::std::mem::transmute(val);
26792:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
26797:            let val: u32 = ::std::mem::transmute(val);
26809:            let flags: u32 = unsafe { ::std::mem::transmute(flags) };
26813:            let disposition: u32 = unsafe { ::std::mem::transmute(disposition) };
26817:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };
26870:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 16u8) as u32) }
26875:            let val: u32 = ::std::mem::transmute(val);
26881:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u32) }
26886:            let val: u32 = ::std::mem::transmute(val);
26892:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
26897:            let val: u32 = ::std::mem::transmute(val);
26909:            let flags: u32 = unsafe { ::std::mem::transmute(flags) };
26913:            let disposition: u32 = unsafe { ::std::mem::transmute(disposition) };
26917:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };
26970:        unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 16u8) as u32) }
26975:            let val: u32 = ::std::mem::transmute(val);
26981:        unsafe { ::std::mem::transmute(self._bitfield_1.get(16usize, 8u8) as u32) }
26986:            let val: u32 = ::std::mem::transmute(val);
26992:        unsafe { ::std::mem::transmute(self._bitfield_1.get(24usize, 8u8) as u32) }
26997:            let val: u32 = ::std::mem::transmute(val);
27009:            let flags: u32 = unsafe { ::std::mem::transmute(flags) };
27013:            let disposition: u32 = unsafe { ::std::mem::transmute(disposition) };
27017:            let type_: u32 = unsafe { ::std::mem::transmute(type_) };

src/lib/fidl/rust/fidl/src/encoding.rs
46:///   transmute from `*const Self::Owned` to `*const u8` and read `inline_size`
50:///   transmute from `*mut Self::Owned` to `*mut u8` and write `inline_size`
519:                    mem::transmute::<*mut u8, *mut u64>(padding_ptr).write_unaligned(0);
562:        let numeric_ptr = mem::transmute::<*mut u8, *mut T>(ptr);
586:            mem::transmute::<*mut u8, *mut u64>(padding_ptr).write_unaligned(0);
611:            mem::transmute::<*mut u8, *mut u64>(padding_ptr).write_unaligned(0);
724:                mem::transmute::<*const u8, *const u64>(last_u64_ptr).read_unaligned()
781:            let numeric_ptr = mem::transmute::<*const u8, *const T>(ptr);
810:            mem::transmute::<*const u8, *const u64>(last_u64_ptr).read_unaligned()
2670:                    #[allow(clippy::transmute_undefined_repr)] // TODO(fxbug.dev/95059)
2671:                    let typed_buf_ptr = std::mem::transmute::<*mut u8, *mut $name>(buf_ptr);
2677:                        let padding_ptr = std::mem::transmute::<*mut u8, *mut $padding_ty_v1>(ptr);
2702:                    let padval = unsafe { std::mem::transmute::<*const u8, *const $padding_ty_v1>(ptr).read_unaligned() };
2712:                    let obj_ptr = std::mem::transmute::<*mut $name, *mut u8>(self);
2825:                            let padval = unsafe { std::mem::transmute::<*const u8, *const $padding_ty_v1>(ptr).read_unaligned() };
2837:                            let padval = unsafe { std::mem::transmute::<*const u8, *const $padding_ty_v2>(ptr).read_unaligned() };
2911:                                std::mem::transmute::<*mut u8, *mut $padding_ty_v1>(ptr).write_unaligned(0);
2919:                                std::mem::transmute::<*mut u8, *mut $padding_ty_v2>(ptr).write_unaligned(0);

src/lib/zircon/rust/src/channel.rs
123:            match self.read_raw(bytes, unsafe { mem::transmute(handle_slice) }) {
230:            match self.read_etc_raw(bytes, unsafe { std::mem::transmute(handle_info_slice) }) {

src/lib/zircon/rust/src/port.rs
102:        // transmute_copy doesn't work because the mem packet is too small and
103:        // transmute_copy requires that Dst is not larger than Src.
106:        // x64 builds work fine with transmute_copy. This is because the
110:            unsafe { mem::transmute(&mem.0) };
123:        // transmute_copy doesn't work because the io packet is too small and
124:        // transmute_copy requires that Dst is not larger than Src.
126:            unsafe { mem::transmute(&io.0) };
137:            union: unsafe { mem::transmute_copy(&vcpu.0) },
161:                    mem::transmute_copy(&self.0.union)
167:                    mem::transmute_copy(&self.0.union)
173:                    mem::transmute_copy(&self.0.union)
179:                    mem::transmute_copy(&self.0.union)
185:                    mem::transmute_copy(&self.0.union)
190:                PacketContents::Pager(PagerPacket(unsafe { mem::transmute_copy(&self.0.union) }))

src/lib/cutex/src/cutex.rs
325:                        std::mem::transmute(&*this.predicate.as_ref())

src/lib/ui/wayland/core/src/fixed.rs
81:            let fixed: Fixed = mem::transmute::<u32, i32>(0xffffff00).into();
84:            let fixed: Fixed = mem::transmute::<u32, i32>(0xfffffeff).into();
99:            assert_eq!(mem::transmute::<u32, i32>(0xffffff00), fixed.bits());
102:            assert_eq!(mem::transmute::<u32, i32>(0xfffffeff), fixed.bits());

src/lib/ui/wayland/bindings/scanner/tests/back_end_test.rs
15:            let value: u32 = zerocopy::transmute!($val);

src/lib/ui/fuchsia-vulkan/src/lib.rs
40:                                ::std::mem::transmute($name as *const ())
42:                                ::std::mem::transmute(val)
405:    vk::EntryPoints::load(|name| unsafe { mem::transmute(vkGetInstanceProcAddr(0, name.as_ptr())) })
410:        mem::transmute(vkGetInstanceProcAddr(instance, name.as_ptr()))

src/lib/diagnostics/log/bench/src/encoding.rs
77:    // See https://github.com/rust-lang/rust/issues/61956 for why we can't use transmute.
79:    unsafe { std::mem::transmute_copy::<_, [ValueSetItem<'a>; N]>(&data) }

src/ui/examples/flatland-view-provider/src/ash_extensions/fuchsia/buffer_collection.rs
22:            mem::transmute(instance.get_device_proc_addr(handle, name.as_ptr()))

src/lib/fuchsia-fs/src/directory/watcher.rs
159:        ::std::mem::transmute(self)

src/testing/metrics-logger/src/cpu_load_logger.rs
399:                std::mem::transmute::<ZbiTopologyNode, [u8; ZBI_TOPOLOGY_NODE_SIZE]>(node)

src/testing/metrics-logger/src/gpu_usage_logger.rs
292:            std::mem::transmute::<

@joshlf joshlf added the compatibility-nonbreaking Changes that are (likely to be) non-breaking label Aug 12, 2023
@joshlf joshlf mentioned this issue Aug 20, 2023
@joshlf
Copy link
Member Author

joshlf commented Aug 29, 2023

Follow up: Would it be sound to implement FromZeroes for raw pointer types? Are there any provenance concerns for null pointers? In other words, for T: Sized, is transmute::<_, *const T>([0u8; size_of::<P>()] sound?

cc @RalfJung since we've been talking about pointer validity and provenance

@digama0
Copy link

digama0 commented Aug 29, 2023

I can't think of any reason this would be problematic. I'm not sure if we document that 0 is the null pointer (I'm guessing we do), but it doesn't need to have provenance in any case.

@joshlf
Copy link
Member Author

joshlf commented Aug 29, 2023

I assume that, despite fat pointers logically containing a thin pointer and a length, the actual layout/bit representation of fat pointers is not guaranteed by the reference, and so it would not be sound to implement FromZeroes for e.g. *const [T]?

joshlf added a commit that referenced this issue Aug 29, 2023
joshlf added a commit that referenced this issue Aug 29, 2023
joshlf added a commit that referenced this issue Aug 29, 2023
@RalfJung
Copy link

RalfJung commented Aug 29, 2023

Transmuting a usize to a thin raw pointer should always be sound, I see no reason why that would not work. The other direction is the problematic one.

(Note that the resulting pointer might be "even less valid than a ptr::invalid pointer", whatever that means. Even zero-sized accesses might be UB. But as long as you never actually do anything with that raw pointer, it's fine. So it might still be better to avoid this operation since users might think they can do things with the resulting pointer that they cannot do. However, for the specific case of 0, users probably don't think they can do much with that pointer anyway...)

I assume that, despite fat pointers logically containing a thin pointer and a length, the actual layout/bit representation of fat pointers is not guaranteed by the reference, and so it would not be sound to implement FromZeroes for e.g. *const [T]?

Layout of wide pointers is indeed undocumented, they may only be created via ptr::from_raw_parts. Note that transmuting a bunch of 0s to *const dyn Trait is insta-UB as of today, we even emit nonnull attributes to LLVM for the vtable (but we might change that in the future).

@joshlf
Copy link
Member Author

joshlf commented Oct 29, 2023

Leaving a note here: if we implement this Clippy lint, then this may be less dangerous, since our transmute! macro desugars to mem::transmute. We'd need to make sure a similar lint would fire in other cases (e.g., today, transmute_ref! and transmute_mut! desugar to other functions, and there are also APIs other than these macros which effectively enable transmutation).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compatibility-nonbreaking Changes that are (likely to be) non-breaking
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants