4 ms·
Hi Steve, I came across this post which presents an example using rust's transmute and it's incorrect behavior when the alignment is different. https://andrewk
by ishanjain28 5y ago
Hi Steve,
I came across this post which presents an example using rust's transmute and it's incorrect behavior when the alignment is different. https://andrewkelley.me/post/unsafe-zig-safer-than-unsafe-rust.html https://andrewkelley.me/post/unsafe-zig-safer-than-unsafe-ru...
Is this issue still present? I tried to figure it out the other day using latest rust's nightly but the llvm ir output has so much going on that I didn't _really_ understand what was going on
- MaulingMonkey 5y agoPer transmute's docs @ https://doc.rust-lang.org/std/mem/fn.transmute.html https://doc.rust-lang.org/std/mem/fn.transmute.html: > Because transmute is a by-value operation, alignment of the transmuted values themselves is not a concern. As with any other function, the compiler already ensures both T and U are properly aligned. However, when transmuting values that point elsewhere (such as pointers, references, boxes…), the caller has to ensure proper alignment of the pointed-to values. The post you've linked transmutes a reference, and as the caller fails to explicitly ensure proper alignment, it explicitly risks invoking undefined behavior - I would consider the code buggy. The easiest way to prove it's broken would be to create an reference that's more likely to be unaligned (&array[1] instead of &array[0]?) and run the code on a less misalignment-tolerant platform (ARM?). Here are some 100% sound alternatives using bytemuck (no unsafe required!) and core::ptr::{read,write}_unaligned (unsafe required): https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=bc30cc223eb8a454ca78338cfbee0a7a https://play.rust-lang.org/?version=stable&mode=debug&editio...
- steveklabnik 5y agoI am unsure about the specific details about IR that's emitted (though at first glance it seems we do emit the alignment attribute now, I think?), but transmute is, as the documentation says, "incredibly" unsafe: > Because transmute is a by-value operation, alignment of the transmuted values themselves is not a concern. As with any other function, the compiler already ensures both T and U are properly aligned. However, when transmuting values that point elsewhere (such as pointers, references, boxes…), the caller has to ensure proper alignment of the pointed-to values. This code is doing the latter incorrectly, and therefore invokes UB, as far as I can tell. To be honest, I don't use transmute very often and so I don't have every single last corner case about it memorized. It's not so much an "issue" as it is "Here's an API that's extremely sharp in Rust, and a similar, but less sharp API in Zig."
- jarpadat 5y agoThat discussion is a bit strange. In that example Foo is implicitly #[repr(Rust)] meaning it has an undefined layout. In particular, a,b is unordered, and even if you don't care which order you get, there is the question of padding (a reasonable compiler will tightly pack a,b but that's not required). For this reason, we never reach the question of alignment because we know neither i32, u8, nor any other type has the same layout as Foo (undefined layout). It is certainly true that unsafe Rust is veeeeery unsafe, as perhaps evidenced by me being the first person to point out the repr issue. On the other hand this scheme has a lot of advantages for writing safe Rust.