Skip to content

Commit

Permalink
Add misaligned_transmute lint
Browse files Browse the repository at this point in the history
  • Loading branch information
devonhollowood committed Jan 25, 2018
1 parent 7812038 commit 0413b3f
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 4 deletions.
1 change: 1 addition & 0 deletions clippy_lints/src/lib.rs
Expand Up @@ -603,6 +603,7 @@ pub fn register_plugins(reg: &mut rustc_plugin::Registry) {
transmute::TRANSMUTE_PTR_TO_REF,
transmute::USELESS_TRANSMUTE,
transmute::WRONG_TRANSMUTE,
transmute::MISALIGNED_TRANSMUTE,
types::ABSURD_EXTREME_COMPARISONS,
types::BORROWED_BOX,
types::BOX_VEC,
Expand Down
35 changes: 33 additions & 2 deletions clippy_lints/src/transmute.rs
Expand Up @@ -3,7 +3,8 @@ use rustc::ty::{self, Ty};
use rustc::hir::*;
use std::borrow::Cow;
use syntax::ast;
use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then};
use utils::{last_path_segment, match_def_path, paths, snippet, span_lint, span_lint_and_then,
alignment};
use utils::{opt_def_id, sugg};

/// **What it does:** Checks for transmutes that can't ever be correct on any
Expand Down Expand Up @@ -168,6 +169,23 @@ declare_lint! {
"transmutes from an integer to a float"
}

/// **What it does:** Checks for transmutes to a potentially less-aligned type.
///
/// **Why is this bad?** This might result in undefined behavior.
///
/// **Known problems:** None.
///
/// **Example:**
/// ```rust
/// // u32 is 32-bit aligned; u8 is 8-bit aligned
/// let _: u32 = unsafe { std::mem::transmute([0u8; 4]) };
/// ```
declare_lint! {
pub MISALIGNED_TRANSMUTE,
Warn,
"transmutes to a potentially less-aligned type"
}

pub struct Transmute;

impl LintPass for Transmute {
Expand All @@ -180,7 +198,8 @@ impl LintPass for Transmute {
TRANSMUTE_INT_TO_CHAR,
TRANSMUTE_BYTES_TO_STR,
TRANSMUTE_INT_TO_BOOL,
TRANSMUTE_INT_TO_FLOAT
TRANSMUTE_INT_TO_FLOAT,
MISALIGNED_TRANSMUTE
)
}
}
Expand All @@ -201,6 +220,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Transmute {
e.span,
&format!("transmute from a type (`{}`) to itself", from_ty),
),
_ if alignment(cx, from_ty).map(|a| a.abi())
< alignment(cx, to_ty).map(|a| a.abi())
=> span_lint(
cx,
MISALIGNED_TRANSMUTE,
e.span,
&format!(
"transmute from `{}` to a less-aligned type (`{}`)",
from_ty,
to_ty,
)
),
(&ty::TyRef(_, rty), &ty::TyRawPtr(ptr_ty)) => span_lint_and_then(
cx,
USELESS_TRANSMUTE,
Expand Down
7 changes: 6 additions & 1 deletion clippy_lints/src/utils/mod.rs
Expand Up @@ -9,7 +9,7 @@ use rustc::lint::{LateContext, Level, Lint, LintContext};
use rustc::session::Session;
use rustc::traits;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::LayoutOf;
use rustc::ty::layout::{LayoutOf, Align};
use rustc_errors;
use std::borrow::Cow;
use std::env;
Expand Down Expand Up @@ -1056,3 +1056,8 @@ pub fn get_arg_name(pat: &Pat) -> Option<ast::Name> {
_ => None,
}
}

/// Returns alignment for a type, or None if alignment is undefined
pub fn alignment<'a, 'tcx>(cx: &LateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Option<Align> {
(cx.tcx, cx.param_env).layout_of(ty).ok().map(|layout| layout.align)
}
7 changes: 7 additions & 0 deletions tests/ui/transmute.rs
Expand Up @@ -140,4 +140,11 @@ fn bytes_to_str(b: &[u8], mb: &mut [u8]) {
let _: &mut str = unsafe { std::mem::transmute(mb) };
}

#[warn(misaligned_transmute)]
fn misaligned_transmute() {
let _: u32 = unsafe { std::mem::transmute([0u8; 4]) }; // err
let _: u32 = unsafe { std::mem::transmute(0f32) }; // ok (alignment-wise)
let _: [u8; 4] = unsafe { std::mem::transmute(0u32) }; // ok (alignment-wise)
}

fn main() { }
10 changes: 9 additions & 1 deletion tests/ui/transmute.stderr
Expand Up @@ -204,5 +204,13 @@ error: transmute from a `&mut [u8]` to a `&mut str`
140 | let _: &mut str = unsafe { std::mem::transmute(mb) };
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `std::str::from_utf8_mut(mb).unwrap()`

error: aborting due to 32 previous errors
error: transmute from `[u8; 4]` to a less-aligned type (`u32`)
--> $DIR/transmute.rs:145:27
|
145 | let _: u32 = unsafe { std::mem::transmute([0u8; 4]) }; // err
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `-D misaligned-transmute` implied by `-D warnings`

error: aborting due to 33 previous errors

0 comments on commit 0413b3f

Please sign in to comment.