From 446acc7e97329254c780cb6af7a98724997d7f9a Mon Sep 17 00:00:00 2001 From: boxdot Date: Sun, 18 Oct 2020 13:42:09 +0200 Subject: [PATCH 1/8] Add invalid null pointer usage lint. --- CHANGELOG.md | 1 + clippy_lints/src/lib.rs | 3 +++ clippy_lints/src/ptr.rs | 41 +++++++++++++++++++++++++++--- clippy_lints/src/utils/paths.rs | 1 + tests/ui/invalid_null_usage.fixed | 6 +++++ tests/ui/invalid_null_usage.rs | 6 +++++ tests/ui/invalid_null_usage.stderr | 16 ++++++++++++ 7 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 tests/ui/invalid_null_usage.fixed create mode 100644 tests/ui/invalid_null_usage.rs create mode 100644 tests/ui/invalid_null_usage.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index b9e4b0e67040..5213501da95c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1872,6 +1872,7 @@ Released 2018-09-13 [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref [`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering +[`invalid_null_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_usage [`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref [`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 67a3a3fcf48a..6fad6e116158 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -797,6 +797,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &pattern_type_mismatch::PATTERN_TYPE_MISMATCH, &precedence::PRECEDENCE, &ptr::CMP_NULL, + &ptr::INVALID_NULL_USAGE, &ptr::MUT_FROM_REF, &ptr::PTR_ARG, &ptr_eq::PTR_EQ, @@ -1522,6 +1523,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL), LintId::of(&precedence::PRECEDENCE), LintId::of(&ptr::CMP_NULL), + LintId::of(&ptr::INVALID_NULL_USAGE), LintId::of(&ptr::MUT_FROM_REF), LintId::of(&ptr::PTR_ARG), LintId::of(&ptr_eq::PTR_EQ), @@ -1845,6 +1847,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&mut_key::MUTABLE_KEY_TYPE), LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS), LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP), + LintId::of(&ptr::INVALID_NULL_USAGE), LintId::of(&ptr::MUT_FROM_REF), LintId::of(&ranges::REVERSED_EMPTY_RANGES), LintId::of(®ex::INVALID_REGEX), diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index dcb643a28aeb..394712b0d90d 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -2,8 +2,8 @@ use crate::utils::ptr::get_spans; use crate::utils::{ - is_allowed, is_type_diagnostic_item, match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_sugg, - span_lint_and_then, walk_ptrs_hir_ty, + is_allowed, is_type_diagnostic_item, match_function_call, match_qpath, match_type, paths, snippet_opt, span_lint, + span_lint_and_sugg, span_lint_and_then, walk_ptrs_hir_ty, }; use if_chain::if_chain; use rustc_errors::Applicability; @@ -119,7 +119,28 @@ declare_clippy_lint! { "fns that create mutable refs from immutable ref args" } -declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF]); +declare_clippy_lint! { + /// **What it does:** This lint checks for invalid usages of `ptr::null`. + /// + /// **Why is this bad?** This causes undefined behavior. + /// + /// **Known problems:** None. + /// + /// **Example:** + /// ```ignore + /// // Bad. Undefined behavior + /// unsafe { std::slice::from_raw_parts(ptr::null(), 0); } + /// ``` + /// + /// // Good + /// unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); } + /// ``` + pub INVALID_NULL_USAGE, + correctness, + "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead." +} + +declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_USAGE]); impl<'tcx> LateLintPass<'tcx> for Ptr { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { @@ -161,6 +182,20 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { "comparing with null is better expressed by the `.is_null()` method", ); } + } else if let Some(args) = match_function_call(cx, expr, &paths::SLICE_FROM_RAW_PARTS) { + if let Some(arg) = args.first() { + if is_null_path(arg) { + span_lint_and_sugg( + cx, + INVALID_NULL_USAGE, + arg.span, + "pointer must be non-null", + "change this to", + "core::ptr::NonNull::dangling().as_ptr()".to_string(), + Applicability::MachineApplicable, + ); + } + } } } } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 829e9a2989c8..ca7d14be4e75 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -116,6 +116,7 @@ pub const RWLOCK_READ_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockReadGu pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"]; pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"]; pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; +pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"]; pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "", "into_vec"]; pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"]; pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"]; diff --git a/tests/ui/invalid_null_usage.fixed b/tests/ui/invalid_null_usage.fixed new file mode 100644 index 000000000000..5fa967dbe3fd --- /dev/null +++ b/tests/ui/invalid_null_usage.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; +} diff --git a/tests/ui/invalid_null_usage.rs b/tests/ui/invalid_null_usage.rs new file mode 100644 index 000000000000..1f158dae458b --- /dev/null +++ b/tests/ui/invalid_null_usage.rs @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null(), 0) }; +} diff --git a/tests/ui/invalid_null_usage.stderr b/tests/ui/invalid_null_usage.stderr new file mode 100644 index 000000000000..7753e28cccae --- /dev/null +++ b/tests/ui/invalid_null_usage.stderr @@ -0,0 +1,16 @@ +error: pointer must be non-null + --> $DIR/invalid_null_usage.rs:4:64 + | +LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null(), 0) }; + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + | + = note: `#[deny(clippy::invalid_null_usage)]` on by default + +error: pointer must be non-null + --> $DIR/invalid_null_usage.rs:5:64 + | +LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null(), 0) }; + | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: aborting due to 2 previous errors + From 8dcc446c1220f2948b8f2f920d105f26cd0976b6 Mon Sep 17 00:00:00 2001 From: boxdot Date: Fri, 20 Nov 2020 17:48:32 +0100 Subject: [PATCH 2/8] Check also for std::ptr::{null, null_mut}. --- clippy_lints/src/ptr.rs | 5 ++++- clippy_lints/src/utils/paths.rs | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 394712b0d90d..f8d79c763d7b 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -356,7 +356,10 @@ fn is_null_path(expr: &Expr<'_>) -> bool { if let ExprKind::Call(ref pathexp, ref args) = expr.kind { if args.is_empty() { if let ExprKind::Path(ref path) = pathexp.kind { - return match_qpath(path, &paths::PTR_NULL) || match_qpath(path, &paths::PTR_NULL_MUT); + return match_qpath(path, &paths::PTR_NULL) + || match_qpath(path, &paths::PTR_NULL_MUT) + || match_qpath(path, &paths::STD_PTR_NULL) + || match_qpath(path, &paths::STD_PTR_NULL_MUT); } } } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index ca7d14be4e75..fa297659abc6 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -125,6 +125,7 @@ pub const STD_CONVERT_IDENTITY: [&str; 3] = ["std", "convert", "identity"]; pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"]; pub const STD_MEM_TRANSMUTE: [&str; 3] = ["std", "mem", "transmute"]; pub const STD_PTR_NULL: [&str; 3] = ["std", "ptr", "null"]; +pub const STD_PTR_NULL_MUT: [&str; 3] = ["std", "ptr", "null_mut"]; pub const STRING: [&str; 3] = ["alloc", "string", "String"]; pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"]; pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"]; From b0844cf248488275bafa7d3e84b581e9e86ceb39 Mon Sep 17 00:00:00 2001 From: boxdot Date: Fri, 20 Nov 2020 17:54:57 +0100 Subject: [PATCH 3/8] Rename lint to invalid_null_ptr_usage. --- CHANGELOG.md | 2 +- clippy_lints/src/lib.rs | 6 +++--- clippy_lints/src/ptr.rs | 6 +++--- tests/ui/invalid_null_ptr_usage.fixed | 6 ++++++ .../ui/{invalid_null_usage.rs => invalid_null_ptr_usage.rs} | 0 ...alid_null_usage.stderr => invalid_null_ptr_usage.stderr} | 6 +++--- tests/ui/invalid_null_usage.fixed | 2 +- 7 files changed, 17 insertions(+), 11 deletions(-) create mode 100644 tests/ui/invalid_null_ptr_usage.fixed rename tests/ui/{invalid_null_usage.rs => invalid_null_ptr_usage.rs} (100%) rename tests/ui/{invalid_null_usage.stderr => invalid_null_ptr_usage.stderr} (80%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5213501da95c..4102159d5522 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1872,7 +1872,7 @@ Released 2018-09-13 [`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array [`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref [`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering -[`invalid_null_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_usage +[`invalid_null_ptr_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_ptr_usage [`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref [`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex [`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6fad6e116158..958a97fce5aa 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -797,7 +797,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: &pattern_type_mismatch::PATTERN_TYPE_MISMATCH, &precedence::PRECEDENCE, &ptr::CMP_NULL, - &ptr::INVALID_NULL_USAGE, + &ptr::INVALID_NULL_PTR_USAGE, &ptr::MUT_FROM_REF, &ptr::PTR_ARG, &ptr_eq::PTR_EQ, @@ -1523,7 +1523,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL), LintId::of(&precedence::PRECEDENCE), LintId::of(&ptr::CMP_NULL), - LintId::of(&ptr::INVALID_NULL_USAGE), + LintId::of(&ptr::INVALID_NULL_PTR_USAGE), LintId::of(&ptr::MUT_FROM_REF), LintId::of(&ptr::PTR_ARG), LintId::of(&ptr_eq::PTR_EQ), @@ -1847,7 +1847,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf: LintId::of(&mut_key::MUTABLE_KEY_TYPE), LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS), LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP), - LintId::of(&ptr::INVALID_NULL_USAGE), + LintId::of(&ptr::INVALID_NULL_PTR_USAGE), LintId::of(&ptr::MUT_FROM_REF), LintId::of(&ranges::REVERSED_EMPTY_RANGES), LintId::of(®ex::INVALID_REGEX), diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index f8d79c763d7b..74453a205a17 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -135,12 +135,12 @@ declare_clippy_lint! { /// // Good /// unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); } /// ``` - pub INVALID_NULL_USAGE, + pub INVALID_NULL_PTR_USAGE, correctness, "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead." } -declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_USAGE]); +declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE]); impl<'tcx> LateLintPass<'tcx> for Ptr { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { @@ -187,7 +187,7 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { if is_null_path(arg) { span_lint_and_sugg( cx, - INVALID_NULL_USAGE, + INVALID_NULL_PTR_USAGE, arg.span, "pointer must be non-null", "change this to", diff --git a/tests/ui/invalid_null_ptr_usage.fixed b/tests/ui/invalid_null_ptr_usage.fixed new file mode 100644 index 000000000000..5fa967dbe3fd --- /dev/null +++ b/tests/ui/invalid_null_ptr_usage.fixed @@ -0,0 +1,6 @@ +// run-rustfix + +fn main() { + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; +} diff --git a/tests/ui/invalid_null_usage.rs b/tests/ui/invalid_null_ptr_usage.rs similarity index 100% rename from tests/ui/invalid_null_usage.rs rename to tests/ui/invalid_null_ptr_usage.rs diff --git a/tests/ui/invalid_null_usage.stderr b/tests/ui/invalid_null_ptr_usage.stderr similarity index 80% rename from tests/ui/invalid_null_usage.stderr rename to tests/ui/invalid_null_ptr_usage.stderr index 7753e28cccae..5ffc4c8625dd 100644 --- a/tests/ui/invalid_null_usage.stderr +++ b/tests/ui/invalid_null_ptr_usage.stderr @@ -1,13 +1,13 @@ error: pointer must be non-null - --> $DIR/invalid_null_usage.rs:4:64 + --> $DIR/invalid_null_ptr_usage.rs:4:64 | LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null(), 0) }; | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` | - = note: `#[deny(clippy::invalid_null_usage)]` on by default + = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default error: pointer must be non-null - --> $DIR/invalid_null_usage.rs:5:64 + --> $DIR/invalid_null_ptr_usage.rs:5:64 | LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null(), 0) }; | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` diff --git a/tests/ui/invalid_null_usage.fixed b/tests/ui/invalid_null_usage.fixed index 5fa967dbe3fd..76d202b4d332 100644 --- a/tests/ui/invalid_null_usage.fixed +++ b/tests/ui/invalid_null_usage.fixed @@ -1,6 +1,6 @@ // run-rustfix fn main() { - let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null(), 0) }; let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; } From d76f8e587082bb91e0dee8f5206e5c8f919430f8 Mon Sep 17 00:00:00 2001 From: boxdot Date: Fri, 20 Nov 2020 17:57:14 +0100 Subject: [PATCH 4/8] Add test for ptr::null_mut. --- tests/ui/invalid_null_ptr_usage.fixed | 2 ++ tests/ui/invalid_null_ptr_usage.rs | 2 ++ tests/ui/invalid_null_ptr_usage.stderr | 14 +++++++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/ui/invalid_null_ptr_usage.fixed b/tests/ui/invalid_null_ptr_usage.fixed index 5fa967dbe3fd..2ae124a33596 100644 --- a/tests/ui/invalid_null_ptr_usage.fixed +++ b/tests/ui/invalid_null_ptr_usage.fixed @@ -3,4 +3,6 @@ fn main() { let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; } diff --git a/tests/ui/invalid_null_ptr_usage.rs b/tests/ui/invalid_null_ptr_usage.rs index 1f158dae458b..a3d38b92107a 100644 --- a/tests/ui/invalid_null_ptr_usage.rs +++ b/tests/ui/invalid_null_ptr_usage.rs @@ -3,4 +3,6 @@ fn main() { let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null(), 0) }; let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null_mut(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null_mut(), 0) }; } diff --git a/tests/ui/invalid_null_ptr_usage.stderr b/tests/ui/invalid_null_ptr_usage.stderr index 5ffc4c8625dd..3885b158800c 100644 --- a/tests/ui/invalid_null_ptr_usage.stderr +++ b/tests/ui/invalid_null_ptr_usage.stderr @@ -12,5 +12,17 @@ error: pointer must be non-null LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null(), 0) }; | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` -error: aborting due to 2 previous errors +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:6:64 + | +LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null_mut(), 0) }; + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:7:64 + | +LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null_mut(), 0) }; + | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: aborting due to 4 previous errors From 8ef5a6de406635b3376819058f6ec57d9eb5f852 Mon Sep 17 00:00:00 2001 From: boxdot Date: Fri, 20 Nov 2020 18:00:09 +0100 Subject: [PATCH 5/8] Address review comments: remove dot (also in CMP_NULL). --- clippy_lints/src/ptr.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 74453a205a17..2813295c5fdb 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -94,7 +94,7 @@ declare_clippy_lint! { /// ``` pub CMP_NULL, style, - "comparing a pointer to a null pointer, suggesting to use `.is_null()` instead." + "comparing a pointer to a null pointer, suggesting to use `.is_null()` instead" } declare_clippy_lint! { @@ -137,7 +137,7 @@ declare_clippy_lint! { /// ``` pub INVALID_NULL_PTR_USAGE, correctness, - "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead." + "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead" } declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_PTR_USAGE]); From e15d0ceb34ccbf799fe69e7bf3b6705d10c219e9 Mon Sep 17 00:00:00 2001 From: boxdot Date: Fri, 20 Nov 2020 18:16:38 +0100 Subject: [PATCH 6/8] Address review comment: extend lint on std::slice::from_raw_parts_mut --- clippy_lints/src/ptr.rs | 32 +++++++++++++++----------- clippy_lints/src/utils/paths.rs | 1 + tests/ui/invalid_null_ptr_usage.fixed | 3 +++ tests/ui/invalid_null_ptr_usage.rs | 3 +++ tests/ui/invalid_null_ptr_usage.stderr | 14 ++++++++++- 5 files changed, 39 insertions(+), 14 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 2813295c5fdb..898801688dc9 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -173,6 +173,9 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + const INVALID_NULL_PTR_USAGE_FNS: [&[&'static str]; 2] = + [&paths::SLICE_FROM_RAW_PARTS, &paths::SLICE_FROM_RAW_PARTS_MUT]; + if let ExprKind::Binary(ref op, ref l, ref r) = expr.kind { if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(l) || is_null_path(r)) { span_lint( @@ -182,19 +185,22 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { "comparing with null is better expressed by the `.is_null()` method", ); } - } else if let Some(args) = match_function_call(cx, expr, &paths::SLICE_FROM_RAW_PARTS) { - if let Some(arg) = args.first() { - if is_null_path(arg) { - span_lint_and_sugg( - cx, - INVALID_NULL_PTR_USAGE, - arg.span, - "pointer must be non-null", - "change this to", - "core::ptr::NonNull::dangling().as_ptr()".to_string(), - Applicability::MachineApplicable, - ); - } + } else if let Some(arg) = INVALID_NULL_PTR_USAGE_FNS + .iter() + .filter_map(|fn_name| match_function_call(cx, expr, fn_name)) + .next() + .and_then(|args| args.first()) + { + if is_null_path(arg) { + span_lint_and_sugg( + cx, + INVALID_NULL_PTR_USAGE, + arg.span, + "pointer must be non-null", + "change this to", + "core::ptr::NonNull::dangling().as_ptr()".to_string(), + Applicability::MachineApplicable, + ); } } } diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index fa297659abc6..0173b06dc3c5 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -117,6 +117,7 @@ pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWrite pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"]; pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"]; pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"]; +pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"]; pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "", "into_vec"]; pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"]; pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"]; diff --git a/tests/ui/invalid_null_ptr_usage.fixed b/tests/ui/invalid_null_ptr_usage.fixed index 2ae124a33596..562b1b6fb3f8 100644 --- a/tests/ui/invalid_null_ptr_usage.fixed +++ b/tests/ui/invalid_null_ptr_usage.fixed @@ -5,4 +5,7 @@ fn main() { let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; + + let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0) }; } diff --git a/tests/ui/invalid_null_ptr_usage.rs b/tests/ui/invalid_null_ptr_usage.rs index a3d38b92107a..d36791b9e150 100644 --- a/tests/ui/invalid_null_ptr_usage.rs +++ b/tests/ui/invalid_null_ptr_usage.rs @@ -5,4 +5,7 @@ fn main() { let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null(), 0) }; let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null_mut(), 0) }; let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null_mut(), 0) }; + + let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(core::ptr::null_mut(), 0) }; } diff --git a/tests/ui/invalid_null_ptr_usage.stderr b/tests/ui/invalid_null_ptr_usage.stderr index 3885b158800c..65382a160220 100644 --- a/tests/ui/invalid_null_ptr_usage.stderr +++ b/tests/ui/invalid_null_ptr_usage.stderr @@ -24,5 +24,17 @@ error: pointer must be non-null LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null_mut(), 0) }; | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` -error: aborting due to 4 previous errors +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:9:68 + | +LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0) }; + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:10:68 + | +LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(core::ptr::null_mut(), 0) }; + | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: aborting due to 6 previous errors From 79ed1c76be16e1159b0bed07acf693744cd75d11 Mon Sep 17 00:00:00 2001 From: boxdot Date: Mon, 23 Nov 2020 20:20:08 +0100 Subject: [PATCH 7/8] Add remaining functions from std::ptr. --- clippy_lints/src/ptr.rs | 68 +++++++++---- clippy_lints/src/utils/paths.rs | 14 +++ tests/ui/invalid_null_ptr_usage.fixed | 50 ++++++++-- tests/ui/invalid_null_ptr_usage.rs | 50 ++++++++-- tests/ui/invalid_null_ptr_usage.stderr | 128 +++++++++++++++++++++---- 5 files changed, 259 insertions(+), 51 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index 898801688dc9..c23836cffe15 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -173,9 +173,6 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - const INVALID_NULL_PTR_USAGE_FNS: [&[&'static str]; 2] = - [&paths::SLICE_FROM_RAW_PARTS, &paths::SLICE_FROM_RAW_PARTS_MUT]; - if let ExprKind::Binary(ref op, ref l, ref r) = expr.kind { if (op.node == BinOpKind::Eq || op.node == BinOpKind::Ne) && (is_null_path(l) || is_null_path(r)) { span_lint( @@ -185,27 +182,58 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { "comparing with null is better expressed by the `.is_null()` method", ); } - } else if let Some(arg) = INVALID_NULL_PTR_USAGE_FNS - .iter() - .filter_map(|fn_name| match_function_call(cx, expr, fn_name)) - .next() - .and_then(|args| args.first()) - { - if is_null_path(arg) { - span_lint_and_sugg( - cx, - INVALID_NULL_PTR_USAGE, - arg.span, - "pointer must be non-null", - "change this to", - "core::ptr::NonNull::dangling().as_ptr()".to_string(), - Applicability::MachineApplicable, - ); - } + } else { + check_invalid_ptr_usage(cx, expr); } } } +fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<()> { + // fn_name, arg_idx + const INVALID_NULL_PTR_USAGE_TABLE: [(&[&str], usize); 20] = [ + (&paths::SLICE_FROM_RAW_PARTS, 0), + (&paths::SLICE_FROM_RAW_PARTS_MUT, 0), + (&paths::PTR_COPY, 0), + (&paths::PTR_COPY, 1), + (&paths::PTR_COPY_NONOVERLAPPING, 0), + (&paths::PTR_COPY_NONOVERLAPPING, 1), + (&paths::PTR_READ, 0), + (&paths::PTR_READ_UNALIGNED, 0), + (&paths::PTR_READ_VOLATILE, 0), + (&paths::PTR_REPLACE, 0), + (&paths::PTR_SLICE_FROM_RAW_PARTS, 0), + (&paths::PTR_SLICE_FROM_RAW_PARTS_MUT, 0), + (&paths::PTR_SWAP, 0), + (&paths::PTR_SWAP, 1), + (&paths::PTR_SWAP_NONOVERLAPPING, 0), + (&paths::PTR_SWAP_NONOVERLAPPING, 1), + (&paths::PTR_WRITE, 0), + (&paths::PTR_WRITE_UNALIGNED, 0), + (&paths::PTR_WRITE_VOLATILE, 0), + (&paths::PTR_WRITE_BYTES, 0), + ]; + + let arg = INVALID_NULL_PTR_USAGE_TABLE + .iter() + .filter_map(|(fn_name, arg_idx)| { + let args = match_function_call(cx, expr, fn_name)?; + args.iter().nth(*arg_idx).filter(|arg| is_null_path(arg)) + }) + .next()?; + + span_lint_and_sugg( + cx, + INVALID_NULL_PTR_USAGE, + arg.span, + "pointer must be non-null", + "change this to", + format!("core::ptr::NonNull::dangling().as_ptr()"), + Applicability::MachineApplicable, + ); + + Some(()) +} + #[allow(clippy::too_many_lines)] fn check_fn(cx: &LateContext<'_>, decl: &FnDecl<'_>, fn_id: HirId, opt_body_id: Option) { let fn_def_id = cx.tcx.hir().local_def_id(fn_id); diff --git a/clippy_lints/src/utils/paths.rs b/clippy_lints/src/utils/paths.rs index 0173b06dc3c5..3eb4f6eadbac 100644 --- a/clippy_lints/src/utils/paths.rs +++ b/clippy_lints/src/utils/paths.rs @@ -92,9 +92,23 @@ pub const PATH_TO_PATH_BUF: [&str; 4] = ["std", "path", "Path", "to_path_buf"]; pub const POLL: [&str; 4] = ["core", "task", "poll", "Poll"]; pub const POLL_PENDING: [&str; 5] = ["core", "task", "poll", "Poll", "Pending"]; pub const POLL_READY: [&str; 5] = ["core", "task", "poll", "Poll", "Ready"]; +pub const PTR_COPY: [&str; 3] = ["core", "ptr", "copy"]; +pub const PTR_COPY_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "copy_nonoverlapping"]; pub const PTR_EQ: [&str; 3] = ["core", "ptr", "eq"]; pub const PTR_NULL: [&str; 3] = ["core", "ptr", "null"]; pub const PTR_NULL_MUT: [&str; 3] = ["core", "ptr", "null_mut"]; +pub const PTR_READ: [&str; 3] = ["core", "ptr", "read"]; +pub const PTR_READ_UNALIGNED: [&str; 3] = ["core", "ptr", "read_unaligned"]; +pub const PTR_READ_VOLATILE: [&str; 3] = ["core", "ptr", "read_volatile"]; +pub const PTR_REPLACE: [&str; 3] = ["core", "ptr", "replace"]; +pub const PTR_SLICE_FROM_RAW_PARTS: [&str; 3] = ["core", "ptr", "slice_from_raw_parts"]; +pub const PTR_SLICE_FROM_RAW_PARTS_MUT: [&str; 3] = ["core", "ptr", "slice_from_raw_parts_mut"]; +pub const PTR_SWAP: [&str; 3] = ["core", "ptr", "swap"]; +pub const PTR_SWAP_NONOVERLAPPING: [&str; 3] = ["core", "ptr", "swap_nonoverlapping"]; +pub const PTR_WRITE: [&str; 3] = ["core", "ptr", "write"]; +pub const PTR_WRITE_BYTES: [&str; 3] = ["core", "intrinsics", "write_bytes"]; +pub const PTR_WRITE_UNALIGNED: [&str; 3] = ["core", "ptr", "write_unaligned"]; +pub const PTR_WRITE_VOLATILE: [&str; 3] = ["core", "ptr", "write_volatile"]; pub const PUSH_STR: [&str; 4] = ["alloc", "string", "String", "push_str"]; pub const RANGE_ARGUMENT_TRAIT: [&str; 3] = ["core", "ops", "RangeBounds"]; pub const RC: [&str; 3] = ["alloc", "rc", "Rc"]; diff --git a/tests/ui/invalid_null_ptr_usage.fixed b/tests/ui/invalid_null_ptr_usage.fixed index 562b1b6fb3f8..2b271b06e5dd 100644 --- a/tests/ui/invalid_null_ptr_usage.fixed +++ b/tests/ui/invalid_null_ptr_usage.fixed @@ -1,11 +1,49 @@ // run-rustfix fn main() { - let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; - let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; - let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; - let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; + unsafe { + let _slice: &[usize] = std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); + let _slice: &[usize] = std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); - let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0) }; - let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0) }; + let _slice: &[usize] = std::slice::from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0); + + std::ptr::copy::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); + std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); + + std::ptr::copy_nonoverlapping::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); + std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); + + struct A; // zero sized struct + assert_eq!(std::mem::size_of::(), 0); + + let _a: A = std::ptr::read(core::ptr::NonNull::dangling().as_ptr()); + let _a: A = std::ptr::read(core::ptr::NonNull::dangling().as_ptr()); + + let _a: A = std::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr()); + let _a: A = std::ptr::read_unaligned(core::ptr::NonNull::dangling().as_ptr()); + + let _a: A = std::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr()); + let _a: A = std::ptr::read_volatile(core::ptr::NonNull::dangling().as_ptr()); + + let _a: A = std::ptr::replace(core::ptr::NonNull::dangling().as_ptr(), A); + + let _slice: *const [usize] = std::ptr::slice_from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); + let _slice: *const [usize] = std::ptr::slice_from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0); + + let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(core::ptr::NonNull::dangling().as_ptr(), 0); + + std::ptr::swap::(core::ptr::NonNull::dangling().as_ptr(), &mut A); + std::ptr::swap::(&mut A, core::ptr::NonNull::dangling().as_ptr()); + + std::ptr::swap_nonoverlapping::(core::ptr::NonNull::dangling().as_ptr(), &mut A, 0); + std::ptr::swap_nonoverlapping::(&mut A, core::ptr::NonNull::dangling().as_ptr(), 0); + + std::ptr::write(core::ptr::NonNull::dangling().as_ptr(), A); + + std::ptr::write_unaligned(core::ptr::NonNull::dangling().as_ptr(), A); + + std::ptr::write_volatile(core::ptr::NonNull::dangling().as_ptr(), A); + + std::ptr::write_bytes::(core::ptr::NonNull::dangling().as_ptr(), 42, 0); + } } diff --git a/tests/ui/invalid_null_ptr_usage.rs b/tests/ui/invalid_null_ptr_usage.rs index d36791b9e150..ae51c52d8af0 100644 --- a/tests/ui/invalid_null_ptr_usage.rs +++ b/tests/ui/invalid_null_ptr_usage.rs @@ -1,11 +1,49 @@ // run-rustfix fn main() { - let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null(), 0) }; - let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null(), 0) }; - let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null_mut(), 0) }; - let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null_mut(), 0) }; + unsafe { + let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0); + let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0); - let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0) }; - let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(core::ptr::null_mut(), 0) }; + let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); + + std::ptr::copy::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); + std::ptr::copy::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); + + std::ptr::copy_nonoverlapping::(std::ptr::null(), std::ptr::NonNull::dangling().as_ptr(), 0); + std::ptr::copy_nonoverlapping::(std::ptr::NonNull::dangling().as_ptr(), std::ptr::null_mut(), 0); + + struct A; // zero sized struct + assert_eq!(std::mem::size_of::(), 0); + + let _a: A = std::ptr::read(std::ptr::null()); + let _a: A = std::ptr::read(std::ptr::null_mut()); + + let _a: A = std::ptr::read_unaligned(std::ptr::null()); + let _a: A = std::ptr::read_unaligned(std::ptr::null_mut()); + + let _a: A = std::ptr::read_volatile(std::ptr::null()); + let _a: A = std::ptr::read_volatile(std::ptr::null_mut()); + + let _a: A = std::ptr::replace(std::ptr::null_mut(), A); + + let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null(), 0); + let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); + + let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0); + + std::ptr::swap::(std::ptr::null_mut(), &mut A); + std::ptr::swap::(&mut A, std::ptr::null_mut()); + + std::ptr::swap_nonoverlapping::(std::ptr::null_mut(), &mut A, 0); + std::ptr::swap_nonoverlapping::(&mut A, std::ptr::null_mut(), 0); + + std::ptr::write(std::ptr::null_mut(), A); + + std::ptr::write_unaligned(std::ptr::null_mut(), A); + + std::ptr::write_volatile(std::ptr::null_mut(), A); + + std::ptr::write_bytes::(std::ptr::null_mut(), 42, 0); + } } diff --git a/tests/ui/invalid_null_ptr_usage.stderr b/tests/ui/invalid_null_ptr_usage.stderr index 65382a160220..08045daa6701 100644 --- a/tests/ui/invalid_null_ptr_usage.stderr +++ b/tests/ui/invalid_null_ptr_usage.stderr @@ -1,40 +1,130 @@ error: pointer must be non-null - --> $DIR/invalid_null_ptr_usage.rs:4:64 + --> $DIR/invalid_null_ptr_usage.rs:5:59 | -LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null(), 0) }; - | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` +LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null(), 0); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` | = note: `#[deny(clippy::invalid_null_ptr_usage)]` on by default error: pointer must be non-null - --> $DIR/invalid_null_ptr_usage.rs:5:64 + --> $DIR/invalid_null_ptr_usage.rs:6:59 | -LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null(), 0) }; - | ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` +LL | let _slice: &[usize] = std::slice::from_raw_parts(std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> $DIR/invalid_null_ptr_usage.rs:6:64 + --> $DIR/invalid_null_ptr_usage.rs:8:63 | -LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null_mut(), 0) }; - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` +LL | let _slice: &[usize] = std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> $DIR/invalid_null_ptr_usage.rs:7:64 + --> $DIR/invalid_null_ptr_usage.rs:19:36 | -LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null_mut(), 0) }; - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` +LL | let _a: A = std::ptr::read(std::ptr::null()); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> $DIR/invalid_null_ptr_usage.rs:9:68 + --> $DIR/invalid_null_ptr_usage.rs:20:36 | -LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(std::ptr::null_mut(), 0) }; - | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` +LL | let _a: A = std::ptr::read(std::ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` error: pointer must be non-null - --> $DIR/invalid_null_ptr_usage.rs:10:68 + --> $DIR/invalid_null_ptr_usage.rs:22:46 | -LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts_mut(core::ptr::null_mut(), 0) }; - | ^^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` +LL | let _a: A = std::ptr::read_unaligned(std::ptr::null()); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` -error: aborting due to 6 previous errors +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:23:46 + | +LL | let _a: A = std::ptr::read_unaligned(std::ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:25:45 + | +LL | let _a: A = std::ptr::read_volatile(std::ptr::null()); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:26:45 + | +LL | let _a: A = std::ptr::read_volatile(std::ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:28:39 + | +LL | let _a: A = std::ptr::replace(std::ptr::null_mut(), A); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:30:69 + | +LL | let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null(), 0); + | ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:31:69 + | +LL | let _slice: *const [usize] = std::ptr::slice_from_raw_parts(std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:33:73 + | +LL | let _slice: *const [usize] = std::ptr::slice_from_raw_parts_mut(std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:35:29 + | +LL | std::ptr::swap::(std::ptr::null_mut(), &mut A); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:36:37 + | +LL | std::ptr::swap::(&mut A, std::ptr::null_mut()); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:38:44 + | +LL | std::ptr::swap_nonoverlapping::(std::ptr::null_mut(), &mut A, 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:39:52 + | +LL | std::ptr::swap_nonoverlapping::(&mut A, std::ptr::null_mut(), 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:41:25 + | +LL | std::ptr::write(std::ptr::null_mut(), A); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:43:35 + | +LL | std::ptr::write_unaligned(std::ptr::null_mut(), A); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:45:34 + | +LL | std::ptr::write_volatile(std::ptr::null_mut(), A); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:47:40 + | +LL | std::ptr::write_bytes::(std::ptr::null_mut(), 42, 0); + | ^^^^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()` + +error: aborting due to 21 previous errors From 4c56ef01efe1d7b398f557403a769f09d63d1682 Mon Sep 17 00:00:00 2001 From: boxdot Date: Mon, 23 Nov 2020 20:32:13 +0100 Subject: [PATCH 8/8] Make clippy happy. --- clippy_lints/src/ptr.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/clippy_lints/src/ptr.rs b/clippy_lints/src/ptr.rs index c23836cffe15..1b7d1f400ae0 100644 --- a/clippy_lints/src/ptr.rs +++ b/clippy_lints/src/ptr.rs @@ -213,13 +213,10 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) - (&paths::PTR_WRITE_BYTES, 0), ]; - let arg = INVALID_NULL_PTR_USAGE_TABLE - .iter() - .filter_map(|(fn_name, arg_idx)| { - let args = match_function_call(cx, expr, fn_name)?; - args.iter().nth(*arg_idx).filter(|arg| is_null_path(arg)) - }) - .next()?; + let arg = INVALID_NULL_PTR_USAGE_TABLE.iter().find_map(|(fn_name, arg_idx)| { + let args = match_function_call(cx, expr, fn_name)?; + args.get(*arg_idx).filter(|arg| is_null_path(arg)) + })?; span_lint_and_sugg( cx, @@ -227,7 +224,7 @@ fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) - arg.span, "pointer must be non-null", "change this to", - format!("core::ptr::NonNull::dangling().as_ptr()"), + "core::ptr::NonNull::dangling().as_ptr()".to_string(), Applicability::MachineApplicable, );