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()), ); } } }