Skip to content

Commit

Permalink
new restriction lint: division_remainder_used
Browse files Browse the repository at this point in the history
  • Loading branch information
Jacherr committed Mar 11, 2024
1 parent 7ee75f8 commit 6184da3
Show file tree
Hide file tree
Showing 6 changed files with 155 additions and 0 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5144,6 +5144,7 @@ Released 2018-09-13
[`disallowed_type`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_type
[`disallowed_types`]: https://rust-lang.github.io/rust-clippy/master/index.html#disallowed_types
[`diverging_sub_expression`]: https://rust-lang.github.io/rust-clippy/master/index.html#diverging_sub_expression
[`division_remainder_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#division_remainder_used
[`doc_link_with_quotes`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_link_with_quotes
[`doc_markdown`]: https://rust-lang.github.io/rust-clippy/master/index.html#doc_markdown
[`double_comparisons`]: https://rust-lang.github.io/rust-clippy/master/index.html#double_comparisons
Expand Down Expand Up @@ -5280,6 +5281,7 @@ Released 2018-09-13
[`int_plus_one`]: https://rust-lang.github.io/rust-clippy/master/index.html#int_plus_one
[`integer_arithmetic`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_arithmetic
[`integer_division`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division
[`integer_division_remainder_used`]: https://rust-lang.github.io/rust-clippy/master/index.html#integer_division_remainder_used
[`into_iter_on_array`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_array
[`into_iter_on_ref`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_on_ref
[`into_iter_without_iter`]: https://rust-lang.github.io/rust-clippy/master/index.html#into_iter_without_iter
Expand Down
1 change: 1 addition & 0 deletions clippy_lints/src/declared_lints.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,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,
Expand Down
50 changes: 50 additions & 0 deletions clippy_lints/src/integer_division_remainder_used.rs
Original file line number Diff line number Diff line change
@@ -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()),
);
}
}
}
2 changes: 2 additions & 0 deletions clippy_lints/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1122,6 +1123,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
store.register_early_pass(|| Box::new(multiple_bound_locations::MultipleBoundLocations));
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(integer_division_remainder_used::IntegerDivisionRemainderUsed));
// add lints here, do not remove this comment, it's used in `new_lint`
}

Expand Down
41 changes: 41 additions & 0 deletions tests/ui/integer_division_remainder_used.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
#![warn(clippy::integer_division_remainder_used)]
#![allow(unused_variables)]
#![allow(clippy::op_ref)]

struct CustomOps(pub i32);
impl std::ops::Div for CustomOps {
type Output = Self;

fn div(self, rhs: Self) -> Self::Output {
Self(self.0 / rhs.0)
}
}
impl std::ops::Rem for CustomOps {
type Output = Self;

fn rem(self, rhs: Self) -> Self::Output {
Self(self.0 % rhs.0)
}
}

fn main() {
// should trigger
let a = 10;
let b = 5;
let c = a / b;
let d = a % b;
let e = &a / b;
let f = a % &b;
let g = &a / &b;
let h = &10 % b;
let i = a / &4;

// should not trigger on custom Div and Rem
let w = CustomOps(3);
let x = CustomOps(4);
let y = w / x;

let w = CustomOps(3);
let x = CustomOps(4);
let z = w % x;
}
59 changes: 59 additions & 0 deletions tests/ui/integer_division_remainder_used.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
error: use of / has been disallowed in this context
--> tests/ui/integer_division_remainder_used.rs:10:14
|
LL | Self(self.0 / rhs.0)
| ^^^^^^^^^^^^^^
|
= note: `-D clippy::integer-division-remainder-used` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::integer_division_remainder_used)]`

error: use of % has been disallowed in this context
--> tests/ui/integer_division_remainder_used.rs:17:14
|
LL | Self(self.0 % rhs.0)
| ^^^^^^^^^^^^^^

error: use of / has been disallowed in this context
--> tests/ui/integer_division_remainder_used.rs:25:13
|
LL | let c = a / b;
| ^^^^^

error: use of % has been disallowed in this context
--> tests/ui/integer_division_remainder_used.rs:26:13
|
LL | let d = a % b;
| ^^^^^

error: use of / has been disallowed in this context
--> tests/ui/integer_division_remainder_used.rs:27:13
|
LL | let e = &a / b;
| ^^^^^^

error: use of % has been disallowed in this context
--> tests/ui/integer_division_remainder_used.rs:28:13
|
LL | let f = a % &b;
| ^^^^^^

error: use of / has been disallowed in this context
--> tests/ui/integer_division_remainder_used.rs:29:13
|
LL | let g = &a / &b;
| ^^^^^^^

error: use of % has been disallowed in this context
--> tests/ui/integer_division_remainder_used.rs:30:13
|
LL | let h = &10 % b;
| ^^^^^^^

error: use of / has been disallowed in this context
--> tests/ui/integer_division_remainder_used.rs:31:13
|
LL | let i = a / &4;
| ^^^^^^

error: aborting due to 9 previous errors

0 comments on commit 6184da3

Please sign in to comment.