@@ -15,6 +15,7 @@ use rustc_lint::{LateContext, LateLintPass};
1515use rustc_middle:: ty;
1616use rustc_session:: { declare_lint_pass, declare_tool_lint} ;
1717use rustc_span:: source_map:: Span ;
18+ use rustc_span:: symbol:: Symbol ;
1819use rustc_span:: { sym, MultiSpan } ;
1920use std:: borrow:: Cow ;
2021
@@ -189,53 +190,50 @@ impl<'tcx> LateLintPass<'tcx> for Ptr {
189190}
190191
191192fn 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
423421fn 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 {
0 commit comments