Skip to content

Commit

Permalink
New lint: zst_offset
Browse files Browse the repository at this point in the history
  • Loading branch information
llogiq committed Nov 14, 2019
1 parent b4f1769 commit 2e17e88
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 2 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 -->
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 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:

Expand Down
3 changes: 3 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -1344,6 +1346,7 @@ pub fn register_plugins(store: &mut lint::LintStore, sess: &Session, conf: &Conf
LintId::of(&methods::STRING_EXTEND_CHARS),
LintId::of(&methods::UNNECESSARY_FOLD),
LintId::of(&methods::WRONG_SELF_CONVENTION),
LintId::of(&methods::ZST_OFFSET),
LintId::of(&misc::TOPLEVEL_REF_ARG),
LintId::of(&misc::ZERO_PTR),
LintId::of(&misc_early::BUILTIN_TYPE_SHADOW),
Expand Down
33 changes: 33 additions & 0 deletions clippy_lints/src/methods/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
style,
"Check for offset calculations on raw pointers to zero-sized types"
}

declare_lint_pass!(Methods => [
OPTION_UNWRAP_USED,
RESULT_UNWRAP_USED,
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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])
},
_ => {},
}

Expand Down Expand Up @@ -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(ty::ParamEnv::empty().and(ty));
if layout.size.bytes() == 0;
then {
span_lint(cx, ZST_OFFSET, expr.span, "offset calculation on zero-sized value");
}
}
}
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; 333] = [
pub const ALL_LINTS: [Lint; 334] = [
Lint {
name: "absurd_extreme_comparisons",
group: "correctness",
Expand Down Expand Up @@ -2338,5 +2338,12 @@ pub const ALL_LINTS: [Lint; 333] = [
deprecation: None,
module: "unicode",
},
Lint {
name: "zst_offset",
group: "style",
desc: "Check for offset calculations on raw pointers to zero-sized types",
deprecation: None,
module: "methods",
},
];
// end lint list, do not remove this comment, it’s used in `update_lints`
12 changes: 12 additions & 0 deletions tests/ui/zero_offset.rs
Original file line number Diff line number Diff line change
@@ -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);
}
}
9 changes: 9 additions & 0 deletions tests/ui/zero_offset.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 2e17e88

Please sign in to comment.