about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJacherr <jwc2002@outlook.com>2024-03-10 00:00:35 +0000
committerJacherr <jwc2002@outlook.com>2024-03-11 22:51:03 +0000
commit100ab4993e33d9d228303ce86abbfbed9abd88f6 (patch)
tree8fa3ef8e9506e10b8ea35d24f97f8c139ec5e6a7
parente22ca036279dd3fc2aaf05dfca78e5088d98b03e (diff)
downloadrust-100ab4993e33d9d228303ce86abbfbed9abd88f6.tar.gz
rust-100ab4993e33d9d228303ce86abbfbed9abd88f6.zip
new restriction lint: `division_remainder_used`
-rw-r--r--CHANGELOG.md2
-rw-r--r--clippy_lints/src/declared_lints.rs1
-rw-r--r--clippy_lints/src/integer_division_remainder_used.rs50
-rw-r--r--clippy_lints/src/lib.rs2
-rw-r--r--tests/ui/integer_division_remainder_used.rs41
-rw-r--r--tests/ui/integer_division_remainder_used.stderr59
6 files changed, 155 insertions, 0 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index c4651cee057..23e8d82e556 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -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
@@ -5281,6 +5282,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
diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs
index 5d1eadfc7a4..c8e148598a2 100644
--- a/clippy_lints/src/declared_lints.rs
+++ b/clippy_lints/src/declared_lints.rs
@@ -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,
diff --git a/clippy_lints/src/integer_division_remainder_used.rs b/clippy_lints/src/integer_division_remainder_used.rs
new file mode 100644
index 00000000000..36dc45ca788
--- /dev/null
+++ b/clippy_lints/src/integer_division_remainder_used.rs
@@ -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()),
+            );
+        }
+    }
+}
diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs
index 70292d3440e..9b22d7565e3 100644
--- a/clippy_lints/src/lib.rs
+++ b/clippy_lints/src/lib.rs
@@ -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`
 }
 
diff --git a/tests/ui/integer_division_remainder_used.rs b/tests/ui/integer_division_remainder_used.rs
new file mode 100644
index 00000000000..5d1b02095d1
--- /dev/null
+++ b/tests/ui/integer_division_remainder_used.rs
@@ -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;
+}
diff --git a/tests/ui/integer_division_remainder_used.stderr b/tests/ui/integer_division_remainder_used.stderr
new file mode 100644
index 00000000000..8adfda28893
--- /dev/null
+++ b/tests/ui/integer_division_remainder_used.stderr
@@ -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
+