New lint: zst_offset

This commit is contained in:
Andre Bogus 2019-11-14 20:18:24 +01:00
parent b4f1769734
commit c21b198576
7 changed files with 67 additions and 2 deletions

View file

@ -1273,4 +1273,5 @@ Released 2018-09-13
[`zero_prefixed_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_prefixed_literal
[`zero_ptr`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_ptr
[`zero_width_space`]: https://rust-lang.github.io/rust-clippy/master/index.html#zero_width_space
[`zst_offset`]: https://rust-lang.github.io/rust-clippy/master/index.html#zst_offset
<!-- end autogenerated links to lint list -->

View file

@ -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 333 lints included in this crate!](https://rust-lang.github.io/rust-clippy/master/index.html)
[There are 334 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:

View file

@ -625,6 +625,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
&methods::USELESS_ASREF,
&methods::WRONG_PUB_SELF_CONVENTION,
&methods::WRONG_SELF_CONVENTION,
&methods::ZST_OFFSET,
&minmax::MIN_MAX,
&misc::CMP_NAN,
&misc::CMP_OWNED,
@ -1177,6 +1178,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
LintId::of(&methods::UNNECESSARY_FOLD),
LintId::of(&methods::USELESS_ASREF),
LintId::of(&methods::WRONG_SELF_CONVENTION),
LintId::of(&methods::ZST_OFFSET),
LintId::of(&minmax::MIN_MAX),
LintId::of(&misc::CMP_NAN),
LintId::of(&misc::CMP_OWNED),
@ -1498,6 +1500,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
LintId::of(&methods::CLONE_DOUBLE_REF),
LintId::of(&methods::TEMPORARY_CSTRING_AS_PTR),
LintId::of(&methods::UNINIT_ASSUMED_INIT),
LintId::of(&methods::ZST_OFFSET),
LintId::of(&minmax::MIN_MAX),
LintId::of(&misc::CMP_NAN),
LintId::of(&misc::FLOAT_CMP),

View file

@ -1065,6 +1065,23 @@ declare_clippy_lint! {
"`.chcked_add/sub(x).unwrap_or(MAX/MIN)`"
}
declare_clippy_lint! {
/// **What it does:** Checks for `offset(_)`, `wrapping_`{`add`, `sub`}, etc. on raw pointers to
/// zero-sized types
///
/// **Why is this bad?** This is a no-op, and likely unintended
///
/// **Known problems:** None
///
/// **Example:**
/// ```ignore
/// unsafe { (&() as *const ()).offest(1) };
/// ```
pub ZST_OFFSET,
correctness,
"Check for offset calculations on raw pointers to zero-sized types"
}
declare_lint_pass!(Methods => [
OPTION_UNWRAP_USED,
RESULT_UNWRAP_USED,
@ -1109,6 +1126,7 @@ declare_lint_pass!(Methods => [
SUSPICIOUS_MAP,
UNINIT_ASSUMED_INIT,
MANUAL_SATURATING_ARITHMETIC,
ZST_OFFSET,
]);
impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
@ -1167,6 +1185,9 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Methods {
| ["unwrap_or", arith @ "checked_mul"] => {
manual_saturating_arithmetic::lint(cx, expr, &arg_lists, &arith["checked_".len()..])
},
["add"] | ["offset"] | ["sub"] | ["wrapping_offset"] | ["wrapping_add"] | ["wrapping_sub"] => {
check_pointer_offset(cx, expr, arg_lists[0])
},
_ => {},
}
@ -3063,3 +3084,15 @@ fn contains_return(expr: &hir::Expr) -> bool {
visitor.visit_expr(expr);
visitor.found
}
fn check_pointer_offset(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) {
if_chain! {
if args.len() == 2;
if let ty::RawPtr(ty::TypeAndMut { ref ty, .. }) = cx.tables.expr_ty(&args[0]).kind;
if let Ok(layout) = cx.tcx.layout_of(cx.param_env.and(ty));
if layout.is_zst();
then {
span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value");
}
}
}

View file

@ -6,7 +6,7 @@ pub use lint::Lint;
pub use lint::LINT_LEVELS;
// begin lint list, do not remove this comment, its used in `update_lints`
pub const ALL_LINTS: [Lint; 333] = [
pub const ALL_LINTS: [Lint; 334] = [
Lint {
name: "absurd_extreme_comparisons",
group: "correctness",
@ -2338,5 +2338,12 @@ pub const ALL_LINTS: [Lint; 333] = [
deprecation: None,
module: "unicode",
},
Lint {
name: "zst_offset",
group: "correctness",
desc: "Check for offset calculations on raw pointers to zero-sized types",
deprecation: None,
module: "methods",
},
];
// end lint list, do not remove this comment, its used in `update_lints`

12
tests/ui/zero_offset.rs Normal file
View file

@ -0,0 +1,12 @@
fn main() {
unsafe {
let x = &() as *const ();
x.offset(0);
x.wrapping_add(0);
x.sub(0);
x.wrapping_sub(0);
let y = &1 as *const u8;
y.offset(0);
}
}

View file

@ -0,0 +1,9 @@
error[E0606]: casting `&i32` as `*const u8` is invalid
--> $DIR/zero_offset.rs:9:17
|
LL | let y = &1 as *const u8;
| ^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0606`.