It appears that the DMA API described in Chapter 8 - DMA is unsafe.
Consider this example. It is basically the motivating example from the "Immovable buffers" section, but with the complete read_exact API from the end of the chapter, including Pining and the 'static bound. The example shows that it is still possible to pass a stack-allocated array into this (supposedly safe) read_exact function, which means the DMA operation will corrupt the stack. All you need to do is wrap the array in a newtype and impl DerefMut for it.
I believe the root of the issue is a misunderstanding of the Pin API. Contrary to intuition, Pin does in most cases not pin the pointed-to data in memory: If the target type implements Unpin, Pin does nothing at all:
Many types are always freely movable, even when pinned, because they do not rely on having a stable address. This includes all the basic types (like bool, i32, and references) as well as types consisting solely of these types. Types that do not care about pinning implement the Unpin auto-trait, which cancels the effect of Pin<P>.
Basically all types we care about implement Unpin (I believe only self-referential types are supposed not to?). Which means Pining the buffer passed into the DMA doesn't help us make the code safe.
The DMA chapter also mentions the StableDeref trait as an alternative. As far as I see, using this would actually lead to a safe API, so we should change the chapter accordingly.
It appears that the DMA API described in Chapter 8 - DMA is unsafe.
Consider this example. It is basically the motivating example from the "Immovable buffers" section, but with the complete
read_exactAPI from the end of the chapter, includingPining and the'staticbound. The example shows that it is still possible to pass a stack-allocated array into this (supposedly safe)read_exactfunction, which means the DMA operation will corrupt the stack. All you need to do is wrap the array in a newtype and implDerefMutfor it.I believe the root of the issue is a misunderstanding of the
PinAPI. Contrary to intuition,Pindoes in most cases not pin the pointed-to data in memory: If the target type implementsUnpin,Pindoes nothing at all:Basically all types we care about implement
Unpin(I believe only self-referential types are supposed not to?). Which meansPining the buffer passed into the DMA doesn't help us make the code safe.The DMA chapter also mentions the
StableDereftrait as an alternative. As far as I see, using this would actually lead to a safe API, so we should change the chapter accordingly.