new restriction lint: division_remainder_used

This commit is contained in:
Jacherr 2024-03-10 00:00:35 +00:00
parent e22ca03627
commit 100ab4993e
6 changed files with 155 additions and 0 deletions

View file

@ -236,6 +236,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
crate::instant_subtraction::MANUAL_INSTANT_ELAPSED_INFO,
crate::instant_subtraction::UNCHECKED_DURATION_SUBTRACTION_INFO,
crate::int_plus_one::INT_PLUS_ONE_INFO,
crate::integer_division_remainder_used::INTEGER_DIVISION_REMAINDER_USED_INFO,
crate::invalid_upcast_comparisons::INVALID_UPCAST_COMPARISONS_INFO,
crate::item_name_repetitions::ENUM_VARIANT_NAMES_INFO,
crate::item_name_repetitions::MODULE_INCEPTION_INFO,

View file

@ -0,0 +1,50 @@
use clippy_utils::diagnostics::span_lint;
use rustc_ast::BinOpKind;
use rustc_hir::{Expr, ExprKind};
use rustc_lint::{LateContext, LateLintPass};
use rustc_middle::ty::{self};
use rustc_session::declare_lint_pass;
declare_clippy_lint! {
/// ### What it does
/// Checks for the usage of division (/) and remainder (%) operations
/// when performed on any integer types using the default Div and Rem trait implementations.
///
/// ### Why is this bad?
/// In cryptographic contexts, division can result in timing sidechannel vulnerabilities,
/// and needs to be replaced with constant-time code instead (e.g. Barrett reduction).
///
/// ### Example
/// ```no_run
/// let my_div = 10 / 2;
/// ```
/// Use instead:
/// ```no_run
/// let my_div = 10 >> 1;
/// ```
#[clippy::version = "1.78.0"]
pub INTEGER_DIVISION_REMAINDER_USED,
restriction,
"use of disallowed default division and remainder operations"
}
declare_lint_pass!(IntegerDivisionRemainderUsed => [INTEGER_DIVISION_REMAINDER_USED]);
impl LateLintPass<'_> for IntegerDivisionRemainderUsed {
fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
if let ExprKind::Binary(op, lhs, rhs) = &expr.kind
&& let BinOpKind::Div | BinOpKind::Rem = op.node
&& let lhs_ty = cx.typeck_results().expr_ty(lhs)
&& let rhs_ty = cx.typeck_results().expr_ty(rhs)
&& let ty::Int(_) | ty::Uint(_) = lhs_ty.peel_refs().kind()
&& let ty::Int(_) | ty::Uint(_) = rhs_ty.peel_refs().kind()
{
span_lint(
cx,
INTEGER_DIVISION_REMAINDER_USED,
expr.span.source_callsite(),
&format!("use of {} has been disallowed in this context", op.node.as_str()),
);
}
}
}

View file

@ -172,6 +172,7 @@ mod init_numbered_fields;
mod inline_fn_without_body;
mod instant_subtraction;
mod int_plus_one;
mod integer_division_remainder_used;
mod invalid_upcast_comparisons;
mod item_name_repetitions;
mod items_after_statements;
@ -1124,6 +1125,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_late_pass(|_| Box::new(assigning_clones::AssigningClones));
store.register_late_pass(|_| Box::new(zero_repeat_side_effects::ZeroRepeatSideEffects));
store.register_late_pass(|_| Box::new(manual_unwrap_or_default::ManualUnwrapOrDefault));
store.register_late_pass(|_| Box::new(integer_division_remainder_used::IntegerDivisionRemainderUsed));
// add lints here, do not remove this comment, it's used in `new_lint`
}