diff --git a/CHANGELOG.md b/CHANGELOG.md index b9e4b0e67040..4102159d5522 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_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 67a3a3fcf48a..958a97fce5aa 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_PTR_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_PTR_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_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 dcb643a28aeb..1b7d1f400ae0 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; @@ -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! { @@ -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_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_PTR_USAGE]); impl<'tcx> LateLintPass<'tcx> for Ptr { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { @@ -161,10 +182,55 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { "comparing with null is better expressed by the `.is_null()` method", ); } + } 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().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, + INVALID_NULL_PTR_USAGE, + arg.span, + "pointer must be non-null", + "change this to", + "core::ptr::NonNull::dangling().as_ptr()".to_string(), + 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); @@ -321,7 +387,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 829e9a2989c8..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"]; @@ -116,6 +130,8 @@ 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_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"]; @@ -124,6 +140,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"]; diff --git a/tests/ui/invalid_null_ptr_usage.fixed b/tests/ui/invalid_null_ptr_usage.fixed new file mode 100644 index 000000000000..2b271b06e5dd --- /dev/null +++ b/tests/ui/invalid_null_ptr_usage.fixed @@ -0,0 +1,49 @@ +// run-rustfix + +fn main() { + 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] = 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 new file mode 100644 index 000000000000..ae51c52d8af0 --- /dev/null +++ b/tests/ui/invalid_null_ptr_usage.rs @@ -0,0 +1,49 @@ +// run-rustfix + +fn main() { + 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] = 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 new file mode 100644 index 000000000000..08045daa6701 --- /dev/null +++ b/tests/ui/invalid_null_ptr_usage.stderr @@ -0,0 +1,130 @@ +error: pointer must be non-null + --> $DIR/invalid_null_ptr_usage.rs:5:59 + | +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:6:59 + | +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:8:63 + | +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:19:36 + | +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:20:36 + | +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:22:46 + | +LL | let _a: A = std::ptr::read_unaligned(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: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 + diff --git a/tests/ui/invalid_null_usage.fixed b/tests/ui/invalid_null_usage.fixed new file mode 100644 index 000000000000..76d202b4d332 --- /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(std::ptr::null(), 0) }; + let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) }; +}