Skip to content

Commit 6f7be88

Browse files
committed
Add invalid null pointer usage lint.
1 parent 86fb0e8 commit 6f7be88

File tree

6 files changed

+68
-1
lines changed

6 files changed

+68
-1
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2266,6 +2266,7 @@ Released 2018-09-13
22662266
[`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array
22672267
[`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
22682268
[`invalid_atomic_ordering`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_atomic_ordering
2269+
[`invalid_null_usage`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_null_usage
22692270
[`invalid_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_ref
22702271
[`invalid_regex`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_regex
22712272
[`invalid_upcast_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#invalid_upcast_comparisons

clippy_lints/src/lib.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -901,6 +901,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
901901
&pattern_type_mismatch::PATTERN_TYPE_MISMATCH,
902902
&precedence::PRECEDENCE,
903903
&ptr::CMP_NULL,
904+
&ptr::INVALID_NULL_USAGE,
904905
&ptr::MUT_FROM_REF,
905906
&ptr::PTR_ARG,
906907
&ptr_eq::PTR_EQ,
@@ -1669,6 +1670,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
16691670
LintId::of(&partialeq_ne_impl::PARTIALEQ_NE_IMPL),
16701671
LintId::of(&precedence::PRECEDENCE),
16711672
LintId::of(&ptr::CMP_NULL),
1673+
LintId::of(&ptr::INVALID_NULL_USAGE),
16721674
LintId::of(&ptr::MUT_FROM_REF),
16731675
LintId::of(&ptr::PTR_ARG),
16741676
LintId::of(&ptr_eq::PTR_EQ),
@@ -2007,6 +2009,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
20072009
LintId::of(&non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
20082010
LintId::of(&open_options::NONSENSICAL_OPEN_OPTIONS),
20092011
LintId::of(&option_env_unwrap::OPTION_ENV_UNWRAP),
2012+
LintId::of(&ptr::INVALID_NULL_USAGE),
20102013
LintId::of(&ptr::MUT_FROM_REF),
20112014
LintId::of(&ranges::REVERSED_EMPTY_RANGES),
20122015
LintId::of(&regex::INVALID_REGEX),

clippy_lints/src/ptr.rs

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,28 @@ declare_clippy_lint! {
119119
"fns that create mutable refs from immutable ref args"
120120
}
121121

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]);
123144

124145
impl<'tcx> LateLintPass<'tcx> for Ptr {
125146
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
@@ -161,6 +182,20 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
161182
"comparing with null is better expressed by the `.is_null()` method",
162183
);
163184
}
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+
}
164199
}
165200
}
166201
}

tests/ui/invalid_null_usage.fixed

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) };
5+
let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::NonNull::dangling().as_ptr(), 0) };
6+
}

tests/ui/invalid_null_usage.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// run-rustfix
2+
3+
fn main() {
4+
let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null(), 0) };
5+
let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null(), 0) };
6+
}

tests/ui/invalid_null_usage.stderr

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error: pointer must be non-null
2+
--> $DIR/invalid_null_usage.rs:4:64
3+
|
4+
LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(std::ptr::null(), 0) };
5+
| ^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
6+
|
7+
= note: `#[deny(clippy::invalid_null_usage)]` on by default
8+
9+
error: pointer must be non-null
10+
--> $DIR/invalid_null_usage.rs:5:64
11+
|
12+
LL | let _slice: &[usize] = unsafe { std::slice::from_raw_parts(core::ptr::null(), 0) };
13+
| ^^^^^^^^^^^^^^^^^ help: change this to: `core::ptr::NonNull::dangling().as_ptr()`
14+
15+
error: aborting due to 2 previous errors
16+

0 commit comments

Comments
 (0)