Add more functions to size_of_in_element_count

Specifically ptr::{sub, wrapping_sub, add, wrapping_add, offset, wrapping_offset} and slice::{from_raw_parts, from_raw_parts_mut}
The lint now also looks for size_of calls through casts (Since offset takes an isize)
This commit is contained in:
unknown 2020-11-30 21:54:50 -03:00
parent af9685bb1e
commit c1a5329475
5 changed files with 128 additions and 43 deletions

View file

@ -848,6 +848,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&shadow::SHADOW_SAME,
&shadow::SHADOW_UNRELATED,
&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS,
&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION,
&stable_sort_primitive::STABLE_SORT_PRIMITIVE,
&strings::STRING_ADD,
@ -917,7 +918,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
&unnecessary_wraps::UNNECESSARY_WRAPS,
&unnested_or_patterns::UNNESTED_OR_PATTERNS,
&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME,
&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT,
&unused_io_amount::UNUSED_IO_AMOUNT,
&unused_self::UNUSED_SELF,
&unused_unit::UNUSED_UNIT,
@ -1562,6 +1562,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&self_assignment::SELF_ASSIGNMENT),
LintId::of(&serde_api::SERDE_API_MISUSE),
LintId::of(&single_component_path_imports::SINGLE_COMPONENT_PATH_IMPORTS),
LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
LintId::of(&slow_vector_initialization::SLOW_VECTOR_INITIALIZATION),
LintId::of(&stable_sort_primitive::STABLE_SORT_PRIMITIVE),
LintId::of(&strings::STRING_FROM_UTF8_AS_BYTES),
@ -1608,7 +1609,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&unnecessary_sort_by::UNNECESSARY_SORT_BY),
LintId::of(&unnecessary_wraps::UNNECESSARY_WRAPS),
LintId::of(&unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME),
LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT),
LintId::of(&unused_unit::UNUSED_UNIT),
LintId::of(&unwrap::PANICKING_UNWRAP),
@ -1872,6 +1872,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&regex::INVALID_REGEX),
LintId::of(&self_assignment::SELF_ASSIGNMENT),
LintId::of(&serde_api::SERDE_API_MISUSE),
LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
LintId::of(&suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL),
LintId::of(&suspicious_trait_impl::SUSPICIOUS_OP_ASSIGN_IMPL),
LintId::of(&swap::ALMOST_SWAPPED),
@ -1887,7 +1888,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
LintId::of(&unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
LintId::of(&unnamed_address::FN_ADDRESS_COMPARISONS),
LintId::of(&unnamed_address::VTABLE_ADDRESS_COMPARISONS),
LintId::of(&size_of_in_element_count::SIZE_OF_IN_ELEMENT_COUNT),
LintId::of(&unused_io_amount::UNUSED_IO_AMOUNT),
LintId::of(&unwrap::PANICKING_UNWRAP),
LintId::of(&vec_resize_to_zero::VEC_RESIZE_TO_ZERO),

View file

@ -54,31 +54,40 @@ fn get_size_of_ty(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<Ty<'tc
ExprKind::Binary(op, left, right) if BinOpKind::Mul == op.node || BinOpKind::Div == op.node => {
get_size_of_ty(cx, left).or_else(|| get_size_of_ty(cx, right))
},
ExprKind::Cast(expr, _) => get_size_of_ty(cx, expr),
_ => None,
}
}
const FUNCTIONS: [[&str; 3]; 6] = [
paths::COPY_NONOVERLAPPING,
paths::COPY,
paths::WRITE_BYTES,
paths::PTR_SWAP_NONOVERLAPPING,
paths::PTR_SLICE_FROM_RAW_PARTS,
paths::PTR_SLICE_FROM_RAW_PARTS_MUT,
];
const METHODS: [&str; 5] = [
"write_bytes",
"copy_to",
"copy_from",
"copy_to_nonoverlapping",
"copy_from_nonoverlapping",
];
fn get_pointee_ty_and_count_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -> Option<(Ty<'tcx>, &'tcx Expr<'tcx>)> {
const FUNCTIONS: [&[&str]; 8] = [
&paths::COPY_NONOVERLAPPING,
&paths::COPY,
&paths::WRITE_BYTES,
&paths::PTR_SWAP_NONOVERLAPPING,
&paths::PTR_SLICE_FROM_RAW_PARTS,
&paths::PTR_SLICE_FROM_RAW_PARTS_MUT,
&paths::SLICE_FROM_RAW_PARTS,
&paths::SLICE_FROM_RAW_PARTS_MUT,
];
const METHODS: [&str; 11] = [
"write_bytes",
"copy_to",
"copy_from",
"copy_to_nonoverlapping",
"copy_from_nonoverlapping",
"add",
"wrapping_add",
"sub",
"wrapping_sub",
"offset",
"wrapping_offset",
];
if_chain! {
// Find calls to ptr::{copy, copy_nonoverlapping}
// and ptr::{swap_nonoverlapping, write_bytes},
if let ExprKind::Call(func, args) = expr.kind;
if let [.., count] = args;
if let ExprKind::Call(func, [.., count]) = expr.kind;
if let ExprKind::Path(ref func_qpath) = func.kind;
if let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id();
if FUNCTIONS.iter().any(|func_path| match_def_path(cx, def_id, func_path));
@ -91,13 +100,12 @@ fn get_pointee_ty_and_count_expr(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) -
};
if_chain! {
// Find calls to copy_{from,to}{,_nonoverlapping} and write_bytes methods
if let ExprKind::MethodCall(method_path, _, args, _) = expr.kind;
if let [ptr_self, _, count] = args;
if let ExprKind::MethodCall(method_path, _, [ptr_self, .., count], _) = expr.kind;
let method_ident = method_path.ident.as_str();
if METHODS.iter().any(|m| *m == &*method_ident);
// Get the pointee type
if let ty::RawPtr(TypeAndMut { ty: pointee_ty, mutbl:_mutability }) =
if let ty::RawPtr(TypeAndMut { ty: pointee_ty, .. }) =
cx.typeck_results().expr_ty(ptr_self).kind();
then {
return Some((pointee_ty, count));
@ -115,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for SizeOfInElementCount {
instead of a count of elements of T";
if_chain! {
// Find calls to unsafe copy functions and get
// Find calls to functions with an element count parameter and get
// the pointee type and count parameter expression
if let Some((pointee_ty, count_expr)) = get_pointee_ty_and_count_expr(cx, expr);

View file

@ -128,6 +128,8 @@ pub const RWLOCK_READ_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockReadGu
pub const RWLOCK_WRITE_GUARD: [&str; 4] = ["std", "sync", "rwlock", "RwLockWriteGuard"];
pub const SERDE_DESERIALIZE: [&str; 3] = ["serde", "de", "Deserialize"];
pub const SERDE_DE_VISITOR: [&str; 3] = ["serde", "de", "Visitor"];
pub const SLICE_FROM_RAW_PARTS: [&str; 4] = ["core", "slice", "raw", "from_raw_parts"];
pub const SLICE_FROM_RAW_PARTS_MUT: [&str; 4] = ["core", "slice", "raw", "from_raw_parts_mut"];
pub const SLICE_INTO_VEC: [&str; 4] = ["alloc", "slice", "<impl [T]>", "into_vec"];
pub const SLICE_ITER: [&str; 4] = ["core", "slice", "iter", "Iter"];
pub const STDERR: [&str; 4] = ["std", "io", "stdio", "stderr"];

View file

@ -1,10 +1,11 @@
#![warn(clippy::size_of_in_element_count)]
#![allow(clippy::ptr_offset_with_cast)]
use std::mem::{size_of, size_of_val};
use std::ptr::{
copy, copy_nonoverlapping, slice_from_raw_parts,
slice_from_raw_parts_mut, swap_nonoverlapping, write_bytes,
copy, copy_nonoverlapping, slice_from_raw_parts, slice_from_raw_parts_mut, swap_nonoverlapping, write_bytes,
};
use std::slice::{from_raw_parts, from_raw_parts_mut};
fn main() {
const SIZE: usize = 128;
@ -33,6 +34,16 @@ fn main() {
slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
y.as_ptr().wrapping_sub(size_of::<u8>());
unsafe { y.as_ptr().add(size_of::<u8>()) };
y.as_mut_ptr().wrapping_add(size_of::<u8>());
unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
// Count expression involving multiplication of size_of (Should trigger the lint)
unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };

View file

@ -1,5 +1,5 @@
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:17:68
--> $DIR/size_of_in_element_count.rs:18:68
|
LL | unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
| ^^^^^^^^^^^^^^^
@ -8,7 +8,7 @@ LL | unsafe { copy_nonoverlapping::<u8>(x.as_ptr(), y.as_mut_ptr(), size_of:
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:18:62
--> $DIR/size_of_in_element_count.rs:19:62
|
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
| ^^^^^^^^^^^^^^^^^^
@ -16,7 +16,7 @@ LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:20:49
--> $DIR/size_of_in_element_count.rs:21:49
|
LL | unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
| ^^^^^^^^^^^^^^^
@ -24,7 +24,7 @@ LL | unsafe { x.as_ptr().copy_to(y.as_mut_ptr(), size_of::<u8>()) };
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:21:64
--> $DIR/size_of_in_element_count.rs:22:64
|
LL | unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8>()) };
| ^^^^^^^^^^^^^^^
@ -32,7 +32,7 @@ LL | unsafe { x.as_ptr().copy_to_nonoverlapping(y.as_mut_ptr(), size_of::<u8
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:22:51
--> $DIR/size_of_in_element_count.rs:23:51
|
LL | unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
| ^^^^^^^^^^^^^^^
@ -40,7 +40,7 @@ LL | unsafe { y.as_mut_ptr().copy_from(x.as_ptr(), size_of::<u8>()) };
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:23:66
--> $DIR/size_of_in_element_count.rs:24:66
|
LL | unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<u8>()) };
| ^^^^^^^^^^^^^^^
@ -48,7 +48,7 @@ LL | unsafe { y.as_mut_ptr().copy_from_nonoverlapping(x.as_ptr(), size_of::<
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:25:47
--> $DIR/size_of_in_element_count.rs:26:47
|
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
| ^^^^^^^^^^^^^^^
@ -56,7 +56,7 @@ LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>()) };
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:26:47
--> $DIR/size_of_in_element_count.rs:27:47
|
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
| ^^^^^^^^^^^^^^^^^^
@ -64,7 +64,7 @@ LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), size_of_val(&x[0])) };
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:28:46
--> $DIR/size_of_in_element_count.rs:29:46
|
LL | unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
| ^^^^^^^^^^^^^^^^^^^^^^
@ -72,7 +72,7 @@ LL | unsafe { y.as_mut_ptr().write_bytes(0u8, size_of::<u8>() * SIZE) };
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:29:47
--> $DIR/size_of_in_element_count.rs:30:47
|
LL | unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
| ^^^^^^^^^^^^^^^^^^^^^^
@ -80,7 +80,7 @@ LL | unsafe { write_bytes(y.as_mut_ptr(), 0u8, size_of::<u8>() * SIZE) };
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:31:66
--> $DIR/size_of_in_element_count.rs:32:66
|
LL | unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<u8>() * SIZE) };
| ^^^^^^^^^^^^^^^^^^^^^^
@ -88,7 +88,7 @@ LL | unsafe { swap_nonoverlapping(y.as_mut_ptr(), x.as_mut_ptr(), size_of::<
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:33:46
--> $DIR/size_of_in_element_count.rs:34:46
|
LL | slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
| ^^^^^^^^^^^^^^^^^^^^^^
@ -96,7 +96,7 @@ LL | slice_from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE);
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:34:38
--> $DIR/size_of_in_element_count.rs:35:38
|
LL | slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
| ^^^^^^^^^^^^^^^^^^^^^^
@ -104,7 +104,71 @@ LL | slice_from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE);
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:37:62
--> $DIR/size_of_in_element_count.rs:37:49
|
LL | unsafe { from_raw_parts_mut(y.as_mut_ptr(), size_of::<u8>() * SIZE) };
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:38:41
|
LL | unsafe { from_raw_parts(y.as_ptr(), size_of::<u8>() * SIZE) };
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:40:33
|
LL | unsafe { y.as_mut_ptr().sub(size_of::<u8>()) };
| ^^^^^^^^^^^^^^^
|
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:41:29
|
LL | y.as_ptr().wrapping_sub(size_of::<u8>());
| ^^^^^^^^^^^^^^^
|
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:42:29
|
LL | unsafe { y.as_ptr().add(size_of::<u8>()) };
| ^^^^^^^^^^^^^^^
|
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:43:33
|
LL | y.as_mut_ptr().wrapping_add(size_of::<u8>());
| ^^^^^^^^^^^^^^^
|
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:44:32
|
LL | unsafe { y.as_ptr().offset(size_of::<u8>() as isize) };
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:45:36
|
LL | y.as_mut_ptr().wrapping_offset(size_of::<u8>() as isize);
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:48:62
|
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>() * SIZE) };
| ^^^^^^^^^^^^^^^^^^^^^^
@ -112,7 +176,7 @@ LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), size_of::<u8>(
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:40:62
--> $DIR/size_of_in_element_count.rs:51:62
|
LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * size_of_val(&x[0]) * 2) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@ -120,12 +184,12 @@ LL | unsafe { copy_nonoverlapping(x.as_ptr(), y.as_mut_ptr(), HALF_SIZE * si
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: found a count of bytes instead of a count of elements of T
--> $DIR/size_of_in_element_count.rs:43:47
--> $DIR/size_of_in_element_count.rs:54:47
|
LL | unsafe { copy(x.as_ptr(), y.as_mut_ptr(), DOUBLE_SIZE * size_of::<u8>() / 2) };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: use a count of elements instead of a count of bytes, it already gets multiplied by the size of the type
error: aborting due to 16 previous errors
error: aborting due to 24 previous errors