|
2 | 2 |
|
3 | 3 | use crate::utils::ptr::get_spans; |
4 | 4 | use crate::utils::{ |
5 | | - is_allowed, is_type_diagnostic_item, match_qpath, match_type, paths, snippet_opt, span_lint, span_lint_and_sugg, |
6 | | - span_lint_and_then, walk_ptrs_hir_ty, |
| 5 | + is_allowed, is_type_diagnostic_item, match_function_call, match_qpath, match_type, paths, snippet_opt, span_lint, |
| 6 | + span_lint_and_sugg, span_lint_and_then, walk_ptrs_hir_ty, |
7 | 7 | }; |
8 | 8 | use if_chain::if_chain; |
9 | 9 | use rustc_errors::Applicability; |
@@ -119,7 +119,28 @@ declare_clippy_lint! { |
119 | 119 | "fns that create mutable refs from immutable ref args" |
120 | 120 | } |
121 | 121 |
|
122 | | -declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF]); |
| 122 | +declare_clippy_lint! { |
| 123 | + /// **What it does:** This lint checks for invalid usages of `ptr::null`. |
| 124 | + /// |
| 125 | + /// **Why is this bad?** This causes undefined behavior. |
| 126 | + /// |
| 127 | + /// **Known problems:** None. |
| 128 | + /// |
| 129 | + /// **Example:** |
| 130 | + /// ```ignore |
| 131 | + /// // Bad. Undefined behavior |
| 132 | + /// unsafe { std::slice::from_raw_parts(ptr::null(), 0); } |
| 133 | + /// ``` |
| 134 | + /// |
| 135 | + /// // Good |
| 136 | + /// unsafe { std::slice::from_raw_parts(NonNull::dangling().as_ptr(), 0); } |
| 137 | + /// ``` |
| 138 | + pub INVALID_NULL_USAGE, |
| 139 | + correctness, |
| 140 | + "invalid usage of a null pointer, suggesting `NonNull::dangling()` instead." |
| 141 | +} |
| 142 | + |
| 143 | +declare_lint_pass!(Ptr => [PTR_ARG, CMP_NULL, MUT_FROM_REF, INVALID_NULL_USAGE]); |
123 | 144 |
|
124 | 145 | impl<'tcx> LateLintPass<'tcx> for Ptr { |
125 | 146 | fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { |
@@ -161,6 +182,20 @@ impl<'tcx> LateLintPass<'tcx> for Ptr { |
161 | 182 | "comparing with null is better expressed by the `.is_null()` method", |
162 | 183 | ); |
163 | 184 | } |
| 185 | + } else if let Some(args) = match_function_call(cx, expr, &paths::SLICE_FROM_RAW_PARTS) { |
| 186 | + if let Some(arg) = args.first() { |
| 187 | + if is_null_path(arg) { |
| 188 | + span_lint_and_sugg( |
| 189 | + cx, |
| 190 | + INVALID_NULL_USAGE, |
| 191 | + arg.span, |
| 192 | + "pointer must be non-null", |
| 193 | + "change this to", |
| 194 | + "core::ptr::NonNull::dangling().as_ptr()".to_string(), |
| 195 | + Applicability::MachineApplicable, |
| 196 | + ); |
| 197 | + } |
| 198 | + } |
164 | 199 | } |
165 | 200 | } |
166 | 201 | } |
|
0 commit comments