You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
ptr's T needs to have the same size and alignment as it was allocated with.
So unlike slices you cannot transmute a type with a greater size or alignment into a type with lesser size or alignment. Even though the above snippet goes from Vec<[u32]> to Vec<[u8]>, it is UB because sizes are different. Even going from Vec<[u32]> to Vec<[u8; 4]> is UB because the alignment of the latter is different.
This is also true when casting a pointer and then feeding it into Vec::from_raw_parts() as described in #4484. I.e. this issue is not specific to transmute(), any attempt to change size and/or alignment of the allocation is UB.
This also applies to other collections that own their allocations such as VecDeque, HashMap/HashSet, BTreeMap/BTreeSet, etc. although I have not seen any transmutes of these in practice.
In the particular case of Vec you can use .as_slice() and work with that. Once you have the slice this can be accomplished using .align_to() or via a pointer cast as described in transmute_ptr_to_ptr lint.
However, there is no way to transmute the collection itself without copying, and there never will be. You must copy the data in this case.
The text was updated successfully, but these errors were encountered:
To make this issue even more serious, this can also lead to an exploitable buffer overflow:
fnmain(){let data:Vec<u8> = vec![1,2,3,4];let optimal_data:Vec<u32> = unsafe{ std::mem::transmute(data)};println!("{:?}", optimal_data);// prints one stable number and then 3 junk numbers}
The vector is expected to have a backing allocation of at least len * size_of(T), which is violated by increasing size_of(T). This failure case could be addressed by implementing either this lint or #4484.
The following snippet is undefined behavior and should crash on Windows:
Excerpt from the docs:
So unlike slices you cannot transmute a type with a greater size or alignment into a type with lesser size or alignment. Even though the above snippet goes from
Vec<[u32]>
toVec<[u8]>
, it is UB because sizes are different. Even going fromVec<[u32]>
toVec<[u8; 4]>
is UB because the alignment of the latter is different.This is also true when casting a pointer and then feeding it into
Vec::from_raw_parts()
as described in #4484. I.e. this issue is not specific totransmute()
, any attempt to change size and/or alignment of the allocation is UB.This also applies to other collections that own their allocations such as VecDeque, HashMap/HashSet, BTreeMap/BTreeSet, etc. although I have not seen any transmutes of these in practice.
In the particular case of Vec you can use
.as_slice()
and work with that. Once you have the slice this can be accomplished using.align_to()
or via a pointer cast as described in transmute_ptr_to_ptr lint.However, there is no way to transmute the collection itself without copying, and there never will be. You must copy the data in this case.
The text was updated successfully, but these errors were encountered: