Skip to content

Commit 336e41d

Browse files
committed
Make the unsafe_sizeof_count_copies lint find copy_{from,to} method calls
1 parent a06f548 commit 336e41d

File tree

3 files changed

+99
-32
lines changed

3 files changed

+99
-32
lines changed

clippy_lints/src/unsafe_sizeof_count_copies.rs

+48-18
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use if_chain::if_chain;
66
use rustc_hir::BinOpKind;
77
use rustc_hir::{Expr, ExprKind};
88
use rustc_lint::{LateContext, LateLintPass};
9-
use rustc_middle::ty::{Ty as TyM, TyS};
9+
use rustc_middle::ty::{self, Ty, TyS, TypeAndMut};
1010
use rustc_session::{declare_lint_pass, declare_tool_lint};
1111

1212
declare_clippy_lint! {
@@ -40,7 +40,7 @@ declare_clippy_lint! {
4040

4141
declare_lint_pass!(UnsafeSizeofCountCopies => [UNSAFE_SIZEOF_COUNT_COPIES]);
4242

43-
fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<TyM<'tcx>> {
43+
fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Ty<'tcx>> {
4444
match &expr.kind {
4545
ExprKind::Call(ref count_func, _func_args) => {
4646
if_chain! {
@@ -62,35 +62,65 @@ fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<TyM<'t
6262
}
6363
}
6464

65+
fn get_pointee_ty_and_count_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> {
66+
if_chain! {
67+
// Find calls to ptr::copy and copy_nonoverlapping
68+
if let ExprKind::Call(ref func, ref args) = expr.kind;
69+
if let [_src, _dest, count] = &**args;
70+
if let ExprKind::Path(ref func_qpath) = func.kind;
71+
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
72+
if match_def_path(cx, def_id, &paths::COPY_NONOVERLAPPING)
73+
|| match_def_path(cx, def_id, &paths::COPY);
74+
75+
// Get the pointee type
76+
if let Some(pointee_ty) = cx.typeck_results().node_substs(func.hir_id).types().next();
77+
then {
78+
return Some((pointee_ty, count));
79+
}
80+
};
81+
if_chain! {
82+
// Find calls to copy_{from,to}{,_nonoverlapping}
83+
if let ExprKind::MethodCall(ref method_path, _, ref args, _) = expr.kind;
84+
if let [ptr_self, _, count] = &**args;
85+
let method_ident = method_path.ident.as_str();
86+
if method_ident== "copy_to" || method_ident == "copy_from"
87+
|| method_ident == "copy_to_nonoverlapping" || method_ident == "copy_from_nonoverlapping";
88+
89+
// Get the pointee type
90+
if let ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl:_mutability }) =
91+
cx.typeck_results().expr_ty(ptr_self).kind();
92+
then {
93+
return Some((pointee_ty, count));
94+
}
95+
};
96+
None
97+
}
98+
6599
impl<'tcx> LateLintPass<'tcx> for UnsafeSizeofCountCopies {
66100
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
67-
if_chain! {
68-
// Find calls to ptr::copy and copy_nonoverlapping
69-
if let ExprKind::Call(ref func, ref func_args) = expr.kind;
70-
if let ExprKind::Path(ref func_qpath) = func.kind;
71-
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
72-
if match_def_path(cx, def_id, &paths::COPY_NONOVERLAPPING)
73-
|| match_def_path(cx, def_id, &paths::COPY);
101+
const HELP_MSG: &str = "use a count of elements instead of a count of bytes \
102+
for the count parameter, it already gets multiplied by the size of the pointed to type";
103+
104+
const LINT_MSG: &str = "unsafe memory copying using a byte count \
105+
(Multiplied by size_of::<T>) instead of a count of T";
74106

75-
// Get the pointee type
76-
let _substs = cx.typeck_results().node_substs(func.hir_id);
77-
if let Some(pointee_ty) = cx.typeck_results().node_substs(func.hir_id).types().next();
107+
if_chain! {
108+
// Find calls to unsafe copy functions and get
109+
// the pointee type and count parameter expression
110+
if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr);
78111

79112
// Find a size_of call in the count parameter expression and
80113
// check that it's the same type
81-
if let [_src, _dest, count] = &**func_args;
82-
if let Some(ty_used_for_size_of) = get_size_of_ty(cx, count);
114+
if let Some(ty_used_for_size_of) = get_size_of_ty(cx, count_expr);
83115
if TyS::same_type(pointee_ty, ty_used_for_size_of);
84116
then {
85117
span_lint_and_help(
86118
cx,
87119
UNSAFE_SIZEOF_COUNT_COPIES,
88120
expr.span,
89-
"unsafe memory copying using a byte count (Multiplied by size_of::<T>) \
90-
instead of a count of T",
121+
LINT_MSG,
91122
None,
92-
"use a count of elements instead of a count of bytes for the count parameter, \
93-
it already gets multiplied by the size of the pointed to type"
123+
HELP_MSG
94124
);
95125
}
96126
};

tests/ui/unsafe_sizeof_count_copies.rs

+5
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@ fn main() {
1414
unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
1515
unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
1616

17+
unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
18+
unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
19+
unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
20+
unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
21+
1722
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
1823
unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
1924

tests/ui/unsafe_sizeof_count_copies.stderr

+46-14
Original file line numberDiff line numberDiff line change
@@ -18,114 +18,146 @@ LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x
1818
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
1919
--> $DIR/unsafe_sizeof_count_copies.rs:17:14
2020
|
21+
LL | unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
22+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
23+
|
24+
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
25+
26+
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
27+
--> $DIR/unsafe_sizeof_count_copies.rs:18:14
28+
|
29+
LL | unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
30+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
31+
|
32+
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
33+
34+
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
35+
--> $DIR/unsafe_sizeof_count_copies.rs:19:14
36+
|
37+
LL | unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
38+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
39+
|
40+
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
41+
42+
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
43+
--> $DIR/unsafe_sizeof_count_copies.rs:20:14
44+
|
45+
LL | unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
46+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47+
|
48+
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
49+
50+
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
51+
--> $DIR/unsafe_sizeof_count_copies.rs:22:14
52+
|
2153
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
2254
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2355
|
2456
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
2557

2658
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
27-
--> $DIR/unsafe_sizeof_count_copies.rs:18:14
59+
--> $DIR/unsafe_sizeof_count_copies.rs:23:14
2860
|
2961
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
3062
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3163
|
3264
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
3365

3466
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
35-
--> $DIR/unsafe_sizeof_count_copies.rs:21:14
67+
--> $DIR/unsafe_sizeof_count_copies.rs:26:14
3668
|
3769
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
3870
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3971
|
4072
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
4173

4274
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
43-
--> $DIR/unsafe_sizeof_count_copies.rs:22:14
75+
--> $DIR/unsafe_sizeof_count_copies.rs:27:14
4476
|
4577
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0]) * SIZE) };
4678
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
4779
|
4880
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
4981

5082
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
51-
--> $DIR/unsafe_sizeof_count_copies.rs:24:14
83+
--> $DIR/unsafe_sizeof_count_copies.rs:29:14
5284
|
5385
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
5486
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
5587
|
5688
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
5789

5890
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
59-
--> $DIR/unsafe_sizeof_count_copies.rs:25:14
91+
--> $DIR/unsafe_sizeof_count_copies.rs:30:14
6092
|
6193
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0]) * SIZE) };
6294
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6395
|
6496
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
6597

6698
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
67-
--> $DIR/unsafe_sizeof_count_copies.rs:28:14
99+
--> $DIR/unsafe_sizeof_count_copies.rs:33:14
68100
|
69101
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * HALF_SIZE * 2) };
70102
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
71103
|
72104
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
73105

74106
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
75-
--> $DIR/unsafe_sizeof_count_copies.rs:29:14
107+
--> $DIR/unsafe_sizeof_count_copies.rs:34:14
76108
|
77109
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
78110
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
79111
|
80112
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
81113

82114
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
83-
--> $DIR/unsafe_sizeof_count_copies.rs:31:14
115+
--> $DIR/unsafe_sizeof_count_copies.rs:36:14
84116
|
85117
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE * HALF_SIZE) };
86118
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
87119
|
88120
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
89121

90122
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
91-
--> $DIR/unsafe_sizeof_count_copies.rs:32:14
123+
--> $DIR/unsafe_sizeof_count_copies.rs:37:14
92124
|
93125
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0]) * HALF_SIZE * 2) };
94126
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
95127
|
96128
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
97129

98130
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
99-
--> $DIR/unsafe_sizeof_count_copies.rs:35:14
131+
--> $DIR/unsafe_sizeof_count_copies.rs:40:14
100132
|
101133
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * DOUBLE_SIZE / 2) };
102134
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
103135
|
104136
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
105137

106138
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
107-
--> $DIR/unsafe_sizeof_count_copies.rs:36:14
139+
--> $DIR/unsafe_sizeof_count_copies.rs:41:14
108140
|
109141
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE / 2 * size_of_val(&x[0])) };
110142
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
111143
|
112144
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
113145

114146
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
115-
--> $DIR/unsafe_sizeof_count_copies.rs:38:14
147+
--> $DIR/unsafe_sizeof_count_copies.rs:43:14
116148
|
117149
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
118150
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
119151
|
120152
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
121153

122154
error: unsafe memory copying using a byte count (Multiplied by size_of::<T>) instead of a count of T
123-
--> $DIR/unsafe_sizeof_count_copies.rs:39:14
155+
--> $DIR/unsafe_sizeof_count_copies.rs:44:14
124156
|
125157
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0]) * DOUBLE_SIZE / 2) };
126158
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
127159
|
128160
= help: use a count of elements instead of a count of bytes for the count parameter, it already gets multiplied by the size of the pointed to type
129161

130-
error: aborting due to 16 previous errors
162+
error: aborting due to 20 previous errors
131163

0 commit comments

Comments
 (0)