Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New lint: zst_offset #4816

Merged
merged 1 commit into from
Nov 23, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -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),
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) };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/offest/offset

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do a followup.

/// ```
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,
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(cx.param_env.and(ty));
if layout.is_zst();
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: "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, 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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't there be errors about offset calculations using x here instead of casting errors for y?

--> $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`.