@@ -15,6 +15,7 @@ use rustc_lint::{LateContext, LateLintPass};
15
15
use rustc_middle:: ty;
16
16
use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
17
17
use rustc_span:: source_map:: Span ;
18
+ use rustc_span:: symbol:: Symbol ;
18
19
use rustc_span:: { sym, MultiSpan } ;
19
20
use std:: borrow:: Cow ;
20
21
@@ -189,53 +190,50 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
189
190
}
190
191
191
192
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 ] ) ,
216
211
] ;
217
212
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
238
225
}
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
+ ) ;
239
237
}
240
238
}
241
239
}
@@ -422,8 +420,7 @@ fn get_rptr_lm<'tcx>(ty: &'tcx Ty<'tcx>) -> Option<(&'tcx Lifetime, Mutability,
422
420
423
421
fn is_null_path ( cx : & LateContext < ' _ > , expr : & Expr < ' _ > ) -> bool {
424
422
if_chain ! {
425
- if let ExprKind :: Call ( path, args) = expr. kind;
426
- if args. is_empty( ) ;
423
+ if let ExprKind :: Call ( path, [ ] ) = expr. kind;
427
424
if let ExprKind :: Path ( ref qpath) = path. kind;
428
425
if let Some ( fn_def_id) = cx. qpath_res( qpath, path. hir_id) . opt_def_id( ) ;
429
426
then {
0 commit comments