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

New lint: unsound_collection_transmute #4592

Merged
merged 1 commit into from
Oct 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,7 @@ Released 2018-09-13
[`unsafe_removed_from_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_removed_from_name
[`unsafe_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_vector_initialization
[`unseparated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#unseparated_literal_suffix
[`unsound_collection_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsound_collection_transmute
[`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice
[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

A collection of lints to catch common mistakes and improve your [Rust](https://github.com/rust-lang/rust) code.

[There are 318 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
[There are 319 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)

We have a bunch of lint categories to allow you to choose how much Clippy is supposed to ~~annoy~~ help you:

Expand Down
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -890,6 +890,7 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry<'_>, conf: &Con
transmute::TRANSMUTE_INT_TO_FLOAT,
transmute::TRANSMUTE_PTR_TO_PTR,
transmute::TRANSMUTE_PTR_TO_REF,
transmute::UNSOUND_COLLECTION_TRANSMUTE,
transmute::USELESS_TRANSMUTE,
transmute::WRONG_TRANSMUTE,
transmuting_null::TRANSMUTING_NULL,
Expand Down Expand Up @@ -1145,6 +1146,7 @@ pub fn register_plugins(reg: &mut rustc_driver::plugin::Registry<'_>, conf: &Con
suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL,
suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL,
swap::ALMOST_SWAPPED,
transmute::UNSOUND_COLLECTION_TRANSMUTE,
transmute::WRONG_TRANSMUTE,
transmuting_null::TRANSMUTING_NULL,
types::ABSURD_EXTREME_COMPARISONS,
Expand Down
530 changes: 300 additions & 230 deletions clippy_lints/src/transmute.rs

Large diffs are not rendered by default.

9 changes: 8 additions & 1 deletion src/lintlist/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ pub use lint::Lint;
pub use lint::LINT_LEVELS;

// begin lint list, do not remove this comment, it’s used in `update_lints`
pub const ALL_LINTS: [Lint; 318] = [
pub const ALL_LINTS: [Lint; 319] = [
Lint {
name: "absurd_extreme_comparisons",
group: "correctness",
Expand Down Expand Up @@ -2030,6 +2030,13 @@ pub const ALL_LINTS: [Lint; 318] = [
deprecation: None,
module: "misc_early",
},
Lint {
name: "unsound_collection_transmute",
group: "correctness",
desc: "transmute between collections of layout-incompatible types",
deprecation: None,
module: "transmute",
},
Lint {
name: "unused_io_amount",
group: "correctness",
Expand Down
6 changes: 0 additions & 6 deletions tests/ui/transmute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,6 @@ fn useless() {

let _: Vec<i32> = my_transmute(my_vec());

let _: Vec<u32> = core::intrinsics::transmute(my_vec());
let _: Vec<u32> = core::mem::transmute(my_vec());
let _: Vec<u32> = std::intrinsics::transmute(my_vec());
let _: Vec<u32> = std::mem::transmute(my_vec());
let _: Vec<u32> = my_transmute(my_vec());

let _: *const usize = std::mem::transmute(5_isize);

let _ = 5_isize as *const usize;
Expand Down
38 changes: 19 additions & 19 deletions tests/ui/transmute.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -117,127 +117,127 @@ LL | let _: Vec<i32> = my_transmute(my_vec());
| ^^^^^^^^^^^^^^^^^^^^^^

error: transmute from an integer to a pointer
--> $DIR/transmute.rs:89:31
--> $DIR/transmute.rs:83:31
|
LL | let _: *const usize = std::mem::transmute(5_isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `5_isize as *const usize`

error: transmute from an integer to a pointer
--> $DIR/transmute.rs:93:31
--> $DIR/transmute.rs:87:31
|
LL | let _: *const usize = std::mem::transmute(1 + 1usize);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `(1 + 1usize) as *const usize`

error: transmute from a type (`*const Usize`) to the type that it points to (`Usize`)
--> $DIR/transmute.rs:108:24
--> $DIR/transmute.rs:102:24
|
LL | let _: Usize = core::intrinsics::transmute(int_const_ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::crosspointer-transmute` implied by `-D warnings`

error: transmute from a type (`*mut Usize`) to the type that it points to (`Usize`)
--> $DIR/transmute.rs:110:24
--> $DIR/transmute.rs:104:24
|
LL | let _: Usize = core::intrinsics::transmute(int_mut_ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from a type (`Usize`) to a pointer to that type (`*const Usize`)
--> $DIR/transmute.rs:112:31
--> $DIR/transmute.rs:106:31
|
LL | let _: *const Usize = core::intrinsics::transmute(my_int());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from a type (`Usize`) to a pointer to that type (`*mut Usize`)
--> $DIR/transmute.rs:114:29
--> $DIR/transmute.rs:108:29
|
LL | let _: *mut Usize = core::intrinsics::transmute(my_int());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from a `u32` to a `char`
--> $DIR/transmute.rs:120:28
--> $DIR/transmute.rs:114:28
|
LL | let _: char = unsafe { std::mem::transmute(0_u32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_u32).unwrap()`
|
= note: `-D clippy::transmute-int-to-char` implied by `-D warnings`

error: transmute from a `i32` to a `char`
--> $DIR/transmute.rs:121:28
--> $DIR/transmute.rs:115:28
|
LL | let _: char = unsafe { std::mem::transmute(0_i32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::char::from_u32(0_i32 as u32).unwrap()`

error: transmute from a `u8` to a `bool`
--> $DIR/transmute.rs:126:28
--> $DIR/transmute.rs:120:28
|
LL | let _: bool = unsafe { std::mem::transmute(0_u8) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `0_u8 != 0`
|
= note: `-D clippy::transmute-int-to-bool` implied by `-D warnings`

error: transmute from a `u32` to a `f32`
--> $DIR/transmute.rs:131:27
--> $DIR/transmute.rs:125:27
|
LL | let _: f32 = unsafe { std::mem::transmute(0_u32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_u32)`
|
= note: `-D clippy::transmute-int-to-float` implied by `-D warnings`

error: transmute from a `i32` to a `f32`
--> $DIR/transmute.rs:132:27
--> $DIR/transmute.rs:126:27
|
LL | let _: f32 = unsafe { std::mem::transmute(0_i32) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `f32::from_bits(0_i32 as u32)`

error: transmute from a `&[u8]` to a `&str`
--> $DIR/transmute.rs:136:28
--> $DIR/transmute.rs:130:28
|
LL | let _: &str = unsafe { std::mem::transmute(b) };
| ^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8(b).unwrap()`
|
= note: `-D clippy::transmute-bytes-to-str` implied by `-D warnings`

error: transmute from a `&mut [u8]` to a `&mut str`
--> $DIR/transmute.rs:137:32
--> $DIR/transmute.rs:131:32
|
LL | let _: &mut str = unsafe { std::mem::transmute(mb) };
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`

error: transmute from a pointer to a pointer
--> $DIR/transmute.rs:169:29
--> $DIR/transmute.rs:163:29
|
LL | let _: *const f32 = std::mem::transmute(ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `ptr as *const f32`
|
= note: `-D clippy::transmute-ptr-to-ptr` implied by `-D warnings`

error: transmute from a pointer to a pointer
--> $DIR/transmute.rs:170:27
--> $DIR/transmute.rs:164:27
|
LL | let _: *mut f32 = std::mem::transmute(mut_ptr);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `mut_ptr as *mut f32`

error: transmute from a reference to a reference
--> $DIR/transmute.rs:172:23
--> $DIR/transmute.rs:166:23
|
LL | let _: &f32 = std::mem::transmute(&1u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1u32 as *const u32 as *const f32)`

error: transmute from a reference to a reference
--> $DIR/transmute.rs:173:23
--> $DIR/transmute.rs:167:23
|
LL | let _: &f64 = std::mem::transmute(&1f32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&1f32 as *const f32 as *const f64)`

error: transmute from a reference to a reference
--> $DIR/transmute.rs:176:27
--> $DIR/transmute.rs:170:27
|
LL | let _: &mut f32 = std::mem::transmute(&mut 1u32);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&mut *(&mut 1u32 as *mut u32 as *mut f32)`

error: transmute from a reference to a reference
--> $DIR/transmute.rs:177:37
--> $DIR/transmute.rs:171:37
|
LL | let _: &GenericParam<f32> = std::mem::transmute(&GenericParam { t: 1u32 });
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `&*(&GenericParam { t: 1u32 } as *const GenericParam<u32> as *const GenericParam<f32>)`
Expand Down
47 changes: 47 additions & 0 deletions tests/ui/transmute_collection.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#![warn(clippy::unsound_collection_transmute)]

use std::collections::{BTreeMap, BTreeSet, BinaryHeap, HashMap, HashSet, VecDeque};
use std::mem::transmute;

fn main() {
unsafe {
// wrong size
let _ = transmute::<_, Vec<u32>>(vec![0u8]);
// wrong layout
let _ = transmute::<_, Vec<[u8; 4]>>(vec![1234u32]);

// wrong size
let _ = transmute::<_, VecDeque<u32>>(VecDeque::<u8>::new());
// wrong layout
let _ = transmute::<_, VecDeque<u32>>(VecDeque::<[u8; 4]>::new());

// wrong size
let _ = transmute::<_, BinaryHeap<u32>>(BinaryHeap::<u8>::new());
// wrong layout
let _ = transmute::<_, BinaryHeap<u32>>(BinaryHeap::<[u8; 4]>::new());

// wrong size
let _ = transmute::<_, BTreeSet<u32>>(BTreeSet::<u8>::new());
// wrong layout
let _ = transmute::<_, BTreeSet<u32>>(BTreeSet::<[u8; 4]>::new());

// wrong size
let _ = transmute::<_, HashSet<u32>>(HashSet::<u8>::new());
// wrong layout
let _ = transmute::<_, HashSet<u32>>(HashSet::<[u8; 4]>::new());

// wrong size
let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u8, u8>::new());
let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u32, u32>::new());
// wrong layout
let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u8, [u8; 4]>::new());
let _ = transmute::<_, BTreeMap<u32, u32>>(BTreeMap::<[u8; 4], u32>::new());

// wrong size
let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u8, u8>::new());
let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u32, u32>::new());
// wrong layout
let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u8, [u8; 4]>::new());
let _ = transmute::<_, HashMap<u32, u32>>(HashMap::<[u8; 4], u32>::new());
}
}
112 changes: 112 additions & 0 deletions tests/ui/transmute_collection.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
error: transmute from `std::vec::Vec<u8>` to `std::vec::Vec<u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:9:17
|
LL | let _ = transmute::<_, Vec<u32>>(vec![0u8]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::unsound-collection-transmute` implied by `-D warnings`

error: transmute from `std::vec::Vec<u32>` to `std::vec::Vec<[u8; 4]>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:11:17
|
LL | let _ = transmute::<_, Vec<[u8; 4]>>(vec![1234u32]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::VecDeque<u8>` to `std::collections::VecDeque<u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:14:17
|
LL | let _ = transmute::<_, VecDeque<u32>>(VecDeque::<u8>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::VecDeque<[u8; 4]>` to `std::collections::VecDeque<u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:16:17
|
LL | let _ = transmute::<_, VecDeque<u32>>(VecDeque::<[u8; 4]>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::BinaryHeap<u8>` to `std::collections::BinaryHeap<u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:19:17
|
LL | let _ = transmute::<_, BinaryHeap<u32>>(BinaryHeap::<u8>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::BinaryHeap<[u8; 4]>` to `std::collections::BinaryHeap<u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:21:17
|
LL | let _ = transmute::<_, BinaryHeap<u32>>(BinaryHeap::<[u8; 4]>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::BTreeSet<u8>` to `std::collections::BTreeSet<u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:24:17
|
LL | let _ = transmute::<_, BTreeSet<u32>>(BTreeSet::<u8>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::BTreeSet<[u8; 4]>` to `std::collections::BTreeSet<u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:26:17
|
LL | let _ = transmute::<_, BTreeSet<u32>>(BTreeSet::<[u8; 4]>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::HashSet<u8>` to `std::collections::HashSet<u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:29:17
|
LL | let _ = transmute::<_, HashSet<u32>>(HashSet::<u8>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::HashSet<[u8; 4]>` to `std::collections::HashSet<u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:31:17
|
LL | let _ = transmute::<_, HashSet<u32>>(HashSet::<[u8; 4]>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::BTreeMap<u8, u8>` to `std::collections::BTreeMap<u8, u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:34:17
|
LL | let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u8, u8>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::BTreeMap<u32, u32>` to `std::collections::BTreeMap<u8, u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:35:17
|
LL | let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u32, u32>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::BTreeMap<u8, [u8; 4]>` to `std::collections::BTreeMap<u8, u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:37:17
|
LL | let _ = transmute::<_, BTreeMap<u8, u32>>(BTreeMap::<u8, [u8; 4]>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::BTreeMap<[u8; 4], u32>` to `std::collections::BTreeMap<u32, u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:38:17
|
LL | let _ = transmute::<_, BTreeMap<u32, u32>>(BTreeMap::<[u8; 4], u32>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::HashMap<u8, u8>` to `std::collections::HashMap<u8, u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:41:17
|
LL | let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u8, u8>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::HashMap<u32, u32>` to `std::collections::HashMap<u8, u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:42:17
|
LL | let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u32, u32>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::HashMap<u8, [u8; 4]>` to `std::collections::HashMap<u8, u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:44:17
|
LL | let _ = transmute::<_, HashMap<u8, u32>>(HashMap::<u8, [u8; 4]>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: transmute from `std::collections::HashMap<[u8; 4], u32>` to `std::collections::HashMap<u32, u32>` with mismatched layout is unsound
--> $DIR/transmute_collection.rs:45:17
|
LL | let _ = transmute::<_, HashMap<u32, u32>>(HashMap::<[u8; 4], u32>::new());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 18 previous errors