1
- //! Lint on unsafe memory copying that use the `size_of` of the pointee type instead of a pointee
2
- //! count
1
+ //! Lint on use of `size_of` or `size_of_val` of T in an expression
2
+ //! expecting a count of T
3
3
4
4
use crate :: utils:: { match_def_path, paths, span_lint_and_help} ;
5
5
use if_chain:: if_chain;
@@ -11,15 +11,11 @@ use rustc_session::{declare_lint_pass, declare_tool_lint};
11
11
12
12
declare_clippy_lint ! {
13
13
/// **What it does:** Detects expressions where
14
- /// size_of::<T> is used as the count argument to unsafe
15
- /// memory copying functions like ptr::copy and
16
- /// ptr::copy_nonoverlapping where T is the pointee type
17
- /// of the pointers used
14
+ /// size_of::<T> or size_of_val::<T> is used as a
15
+ /// count of elements of type T
18
16
///
19
17
/// **Why is this bad?** These functions expect a count
20
- /// of T and not a number of bytes, which can lead to
21
- /// copying the incorrect amount of bytes, which can
22
- /// result in Undefined Behaviour
18
+ /// of T and not a number of bytes
23
19
///
24
20
/// **Known problems:** None.
25
21
///
@@ -33,12 +29,12 @@ declare_clippy_lint! {
33
29
/// let mut y = [2u8; SIZE];
34
30
/// unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
35
31
/// ```
36
- pub UNSAFE_SIZEOF_COUNT_COPIES ,
32
+ pub SIZE_OF_IN_ELEMENT_COUNT ,
37
33
correctness,
38
- "unsafe memory copying using a byte count instead of a count of T"
34
+ "using size_of::<T> or size_of_val::<T> where a count of elements of T is expected "
39
35
}
40
36
41
- declare_lint_pass ! ( UnsafeSizeofCountCopies => [ UNSAFE_SIZEOF_COUNT_COPIES ] ) ;
37
+ declare_lint_pass ! ( SizeOfInElementCount => [ SIZE_OF_IN_ELEMENT_COUNT ] ) ;
42
38
43
39
fn get_size_of_ty ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) -> Option < Ty < ' tcx > > {
44
40
match expr. kind {
@@ -62,18 +58,30 @@ fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Ty<'tc
62
58
}
63
59
}
64
60
61
+ const FUNCTIONS : [ [ & str ; 3 ] ; 6 ] = [
62
+ paths:: COPY_NONOVERLAPPING ,
63
+ paths:: COPY ,
64
+ paths:: WRITE_BYTES ,
65
+ paths:: PTR_SWAP_NONOVERLAPPING ,
66
+ paths:: PTR_SLICE_FROM_RAW_PARTS ,
67
+ paths:: PTR_SLICE_FROM_RAW_PARTS_MUT ,
68
+ ] ;
69
+ const METHODS : [ & str ; 5 ] = [
70
+ "write_bytes" ,
71
+ "copy_to" ,
72
+ "copy_from" ,
73
+ "copy_to_nonoverlapping" ,
74
+ "copy_from_nonoverlapping" ,
75
+ ] ;
65
76
fn get_pointee_ty_and_count_expr ( cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) -> Option < ( Ty < ' tcx > , & ' tcx Expr < ' tcx > ) > {
66
77
if_chain ! {
67
78
// Find calls to ptr::{copy, copy_nonoverlapping}
68
79
// and ptr::{swap_nonoverlapping, write_bytes},
69
80
if let ExprKind :: Call ( func, args) = expr. kind;
70
- if let [ _ , _ , count] = args;
81
+ if let [ .. , count] = args;
71
82
if let ExprKind :: Path ( ref func_qpath) = func. kind;
72
83
if let Some ( def_id) = cx. qpath_res( func_qpath, func. hir_id) . opt_def_id( ) ;
73
- if match_def_path( cx, def_id, & paths:: COPY_NONOVERLAPPING )
74
- || match_def_path( cx, def_id, & paths:: COPY )
75
- || match_def_path( cx, def_id, & paths:: WRITE_BYTES )
76
- || match_def_path( cx, def_id, & paths:: PTR_SWAP_NONOVERLAPPING ) ;
84
+ if FUNCTIONS . iter( ) . any( |func_path| match_def_path( cx, def_id, func_path) ) ;
77
85
78
86
// Get the pointee type
79
87
if let Some ( pointee_ty) = cx. typeck_results( ) . node_substs( func. hir_id) . types( ) . next( ) ;
@@ -86,8 +94,7 @@ fn get_pointee_ty_and_count_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -
86
94
if let ExprKind :: MethodCall ( method_path, _, args, _) = expr. kind;
87
95
if let [ ptr_self, _, count] = args;
88
96
let method_ident = method_path. ident. as_str( ) ;
89
- if method_ident == "write_bytes" || method_ident == "copy_to" || method_ident == "copy_from"
90
- || method_ident == "copy_to_nonoverlapping" || method_ident == "copy_from_nonoverlapping" ;
97
+ if METHODS . iter( ) . any( |m| * m == & * method_ident) ;
91
98
92
99
// Get the pointee type
93
100
if let ty:: RawPtr ( TypeAndMut { ty: pointee_ty, mutbl: _mutability } ) =
@@ -96,31 +103,16 @@ fn get_pointee_ty_and_count_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -
96
103
return Some ( ( pointee_ty, count) ) ;
97
104
}
98
105
} ;
99
- if_chain ! {
100
- // Find calls to ptr::copy and copy_nonoverlapping
101
- if let ExprKind :: Call ( func, args) = expr. kind;
102
- if let [ _data, count] = args;
103
- if let ExprKind :: Path ( ref func_qpath) = func. kind;
104
- if let Some ( def_id) = cx. qpath_res( func_qpath, func. hir_id) . opt_def_id( ) ;
105
- if match_def_path( cx, def_id, & paths:: PTR_SLICE_FROM_RAW_PARTS )
106
- || match_def_path( cx, def_id, & paths:: PTR_SLICE_FROM_RAW_PARTS_MUT ) ;
107
-
108
- // Get the pointee type
109
- if let Some ( pointee_ty) = cx. typeck_results( ) . node_substs( func. hir_id) . types( ) . next( ) ;
110
- then {
111
- return Some ( ( pointee_ty, count) ) ;
112
- }
113
- } ;
114
106
None
115
107
}
116
108
117
- impl < ' tcx > LateLintPass < ' tcx > for UnsafeSizeofCountCopies {
109
+ impl < ' tcx > LateLintPass < ' tcx > for SizeOfInElementCount {
118
110
fn check_expr ( & mut self , cx : & LateContext < ' tcx > , expr : & ' tcx Expr < ' _ > ) {
119
- const HELP_MSG : & str = "use a count of elements instead of a count of bytes \
120
- for the count parameter , it already gets multiplied by the size of the pointed to type";
111
+ const HELP_MSG : & str = "use a count of elements instead of a count of bytes\
112
+ , it already gets multiplied by the size of the type";
121
113
122
- const LINT_MSG : & str = "unsafe memory copying using a byte count \
123
- (multiplied by size_of/size_of_val::<T>) instead of a count of T";
114
+ const LINT_MSG : & str = "found a count of bytes \
115
+ instead of a count of elements of T";
124
116
125
117
if_chain ! {
126
118
// Find calls to unsafe copy functions and get
@@ -134,8 +126,8 @@ impl<'tcx> LateLintPass<'tcx> for UnsafeSizeofCountCopies {
134
126
then {
135
127
span_lint_and_help(
136
128
cx,
137
- UNSAFE_SIZEOF_COUNT_COPIES ,
138
- expr . span,
129
+ SIZE_OF_IN_ELEMENT_COUNT ,
130
+ count_expr . span,
139
131
LINT_MSG ,
140
132
None ,
141
133
HELP_MSG
0 commit comments