Merge pull request #2400 from devonhollowood/misaligned-transmute

Add misaligned_transmute lint
This commit is contained in:
Manish Goregaokar 2018-01-25 14:43:09 +05:30 committed by GitHub
commit c251120756
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
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)
}

View File

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

View File

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