Add misaligned_transmute lint

This commit is contained in:
Devon Hollowood 2018-01-25 00:33:41 -08:00
parent 7812038206
commit 0413b3f6cf
5 changed files with 56 additions and 4 deletions

View file

@ -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,

View file

@ -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
@ -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 {
@ -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
)
}
}
@ -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,

View file

@ -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;
@ -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)
}