Skip to content

Commit c0a002f

Browse files
committed
fixup! Add invalid null pointer usage lint.
1 parent 39ae3c2 commit c0a002f

File tree

2 files changed

+43
-47
lines changed

2 files changed

+43
-47
lines changed

clippy_lints/src/ptr.rs

Lines changed: 43 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use rustc_lint::{LateContext, LateLintPass};
1515
use rustc_middle::ty;
1616
use rustc_session::{declare_lint_pass, declare_tool_lint};
1717
use rustc_span::source_map::Span;
18+
use rustc_span::symbol::Symbol;
1819
use rustc_span::{sym, MultiSpan};
1920
use std::borrow::Cow;
2021

@@ -189,53 +190,50 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
189190
}
190191

191192
fn check_invalid_ptr_usage<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
192-
// (fn_path, arg_idx, num_args) -
193-
// `arg_idx` is the `arg` position where null would cause U.B.
194-
// `num_args` is the numbers of arguments of the function
195-
const INVALID_NULL_PTR_USAGE_TABLE: [(&[&str], usize, usize); 20] = [
196-
(&paths::SLICE_FROM_RAW_PARTS, 0, 2),
197-
(&paths::SLICE_FROM_RAW_PARTS_MUT, 0, 2),
198-
(&paths::PTR_COPY, 0, 3),
199-
(&paths::PTR_COPY, 1, 3),
200-
(&paths::PTR_COPY_NONOVERLAPPING, 0, 3),
201-
(&paths::PTR_COPY_NONOVERLAPPING, 1, 3),
202-
(&paths::PTR_READ, 0, 1),
203-
(&paths::PTR_READ_UNALIGNED, 0, 1),
204-
(&paths::PTR_READ_VOLATILE, 0, 1),
205-
(&paths::PTR_REPLACE, 0, 2),
206-
(&paths::PTR_SLICE_FROM_RAW_PARTS, 0, 2),
207-
(&paths::PTR_SLICE_FROM_RAW_PARTS_MUT, 0, 2),
208-
(&paths::PTR_SWAP, 0, 2),
209-
(&paths::PTR_SWAP, 1, 2),
210-
(&paths::PTR_SWAP_NONOVERLAPPING, 0, 3),
211-
(&paths::PTR_SWAP_NONOVERLAPPING, 1, 3),
212-
(&paths::PTR_WRITE, 0, 2),
213-
(&paths::PTR_WRITE_UNALIGNED, 0, 2),
214-
(&paths::PTR_WRITE_VOLATILE, 0, 2),
215-
(&paths::PTR_WRITE_BYTES, 0, 3),
193+
// (fn_path, arg_indices) - `arg_indices` are the `arg` positions where null would cause U.B.
194+
const INVALID_NULL_PTR_USAGE_TABLE: [(&[&str], &[usize]); 16] = [
195+
(&paths::SLICE_FROM_RAW_PARTS, &[0]),
196+
(&paths::SLICE_FROM_RAW_PARTS_MUT, &[0]),
197+
(&paths::PTR_COPY, &[0, 1]),
198+
(&paths::PTR_COPY_NONOVERLAPPING, &[0, 1]),
199+
(&paths::PTR_READ, &[0]),
200+
(&paths::PTR_READ_UNALIGNED, &[0]),
201+
(&paths::PTR_READ_VOLATILE, &[0]),
202+
(&paths::PTR_REPLACE, &[0]),
203+
(&paths::PTR_SLICE_FROM_RAW_PARTS, &[0]),
204+
(&paths::PTR_SLICE_FROM_RAW_PARTS_MUT, &[0]),
205+
(&paths::PTR_SWAP, &[0, 1]),
206+
(&paths::PTR_SWAP_NONOVERLAPPING, &[0, 1]),
207+
(&paths::PTR_WRITE, &[0]),
208+
(&paths::PTR_WRITE_UNALIGNED, &[0]),
209+
(&paths::PTR_WRITE_VOLATILE, &[0]),
210+
(&paths::PTR_WRITE_BYTES, &[0]),
216211
];
217212

218-
for (fn_path, arg_idx, num_args) in &INVALID_NULL_PTR_USAGE_TABLE {
219-
if_chain! {
220-
if let ExprKind::Call(ref fun, ref args) = expr.kind;
221-
if args.len() == *num_args;
222-
if let ExprKind::Path(ref qpath) = fun.kind;
223-
if let Some(arg) = args.get(*arg_idx);
224-
if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
225-
if match_def_path(cx, fun_def_id, fn_path);
226-
if is_null_path(cx, arg);
227-
then {
228-
span_lint_and_sugg(
229-
cx,
230-
INVALID_NULL_PTR_USAGE,
231-
arg.span,
232-
"pointer must be non-null",
233-
"change this to",
234-
"core::ptr::NonNull::dangling().as_ptr()".to_string(),
235-
Applicability::MachineApplicable,
236-
);
237-
return;
213+
if_chain! {
214+
if let ExprKind::Call(ref fun, ref args) = expr.kind;
215+
if let ExprKind::Path(ref qpath) = fun.kind;
216+
if let Some(fun_def_id) = cx.qpath_res(qpath, fun.hir_id).opt_def_id();
217+
let fun_def_path = cx.get_def_path(fun_def_id).into_iter().map(Symbol::to_ident_string).collect::<Vec<_>>();
218+
if let Some(arg) = INVALID_NULL_PTR_USAGE_TABLE.iter().find_map(|(fn_path, arg_indices)| {
219+
if fn_path == &fun_def_path {
220+
arg_indices.iter().find_map(|arg_idx| {
221+
args.get(*arg_idx).filter(|arg| is_null_path(cx, arg))
222+
})
223+
} else {
224+
None
238225
}
226+
});
227+
then {
228+
span_lint_and_sugg(
229+
cx,
230+
INVALID_NULL_PTR_USAGE,
231+
arg.span,
232+
"pointer must be non-null",
233+
"change this to",
234+
"core::ptr::NonNull::dangling().as_ptr()".to_string(),
235+
Applicability::MachineApplicable,
236+
);
239237
}
240238
}
241239
}
@@ -422,8 +420,7 @@ fn get_rptr_lm<'tcx>(ty: &'tcx Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability,
422420

423421
fn is_null_path(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
424422
if_chain! {
425-
if let ExprKind::Call(path, args) = expr.kind;
426-
if args.is_empty();
423+
if let ExprKind::Call(path, []) = expr.kind;
427424
if let ExprKind::Path(ref qpath) = path.kind;
428425
if let Some(fn_def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id();
429426
then {

clippy_utils/src/paths.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ pub const STD_CONVERT_IDENTITY: [&str; 3] = ["std", "convert", "identity"];
144144
pub const STD_FS_CREATE_DIR: [&str; 3] = ["std", "fs", "create_dir"];
145145
pub const STD_MEM_TRANSMUTE: [&str; 3] = ["std", "mem", "transmute"];
146146
pub const STD_PTR_NULL: [&str; 3] = ["std", "ptr", "null"];
147-
pub const STD_PTR_NULL_MUT: [&str; 3] = ["std", "ptr", "null_mut"];
148147
pub const STRING_AS_MUT_STR: [&str; 4] = ["alloc", "string", "String", "as_mut_str"];
149148
pub const STRING_AS_STR: [&str; 4] = ["alloc", "string", "String", "as_str"];
150149
pub const STR_ENDS_WITH: [&str; 4] = ["core", "str", "<impl str>", "ends_with"];

0 commit comments

Comments
 (0)