forked from rust-lang/rust
-
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Auto merge of rust-lang#12944 - Jarcho:overflow_check, r=y21
Fix and rename `overflow_check_conditional` fixes rust-lang#2457 Other changes: * Limit the lint to unsigned types. * Actually check if the operands are the same rather than using only the first part of the path. * Allow the repeated expression to be anything as long as there are no side effects. changelog: Rename `overflow_check_conditional` to `panicking_overflow_check` and move to `correctness`
- Loading branch information
Showing
13 changed files
with
229 additions
and
222 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
use clippy_utils::diagnostics::span_lint; | ||
use clippy_utils::eq_expr_value; | ||
use rustc_hir::{BinOpKind, Expr, ExprKind}; | ||
use rustc_lint::{LateContext, LateLintPass}; | ||
use rustc_middle::lint::in_external_macro; | ||
use rustc_middle::ty; | ||
use rustc_session::declare_lint_pass; | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// Detects C-style underflow/overflow checks. | ||
/// | ||
/// ### Why is this bad? | ||
/// These checks will, by default, panic in debug builds rather than check | ||
/// whether the operation caused an overflow. | ||
/// | ||
/// ### Example | ||
/// ```no_run | ||
/// # let a = 1i32; | ||
/// # let b = 2i32; | ||
/// if a + b < a { | ||
/// // handle overflow | ||
/// } | ||
/// ``` | ||
/// | ||
/// Use instead: | ||
/// ```no_run | ||
/// # let a = 1i32; | ||
/// # let b = 2i32; | ||
/// if a.checked_add(b).is_none() { | ||
/// // handle overflow | ||
/// } | ||
/// ``` | ||
/// | ||
/// Or: | ||
/// ```no_run | ||
/// # let a = 1i32; | ||
/// # let b = 2i32; | ||
/// if a.overflowing_add(b).1 { | ||
/// // handle overflow | ||
/// } | ||
/// ``` | ||
#[clippy::version = "pre 1.29.0"] | ||
pub PANICKING_OVERFLOW_CHECKS, | ||
correctness, | ||
"overflow checks which will panic in debug mode" | ||
} | ||
|
||
declare_lint_pass!(PanickingOverflowChecks => [PANICKING_OVERFLOW_CHECKS]); | ||
|
||
impl<'tcx> LateLintPass<'tcx> for PanickingOverflowChecks { | ||
// a + b < a, a > a + b, a < a - b, a - b > a | ||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { | ||
if let ExprKind::Binary(op, lhs, rhs) = expr.kind | ||
&& let (lt, gt) = match op.node { | ||
BinOpKind::Lt => (lhs, rhs), | ||
BinOpKind::Gt => (rhs, lhs), | ||
_ => return, | ||
} | ||
&& let ctxt = expr.span.ctxt() | ||
&& let (op_lhs, op_rhs, other, commutative) = match (<.kind, >.kind) { | ||
(&ExprKind::Binary(op, lhs, rhs), _) if op.node == BinOpKind::Add && ctxt == lt.span.ctxt() => { | ||
(lhs, rhs, gt, true) | ||
}, | ||
(_, &ExprKind::Binary(op, lhs, rhs)) if op.node == BinOpKind::Sub && ctxt == gt.span.ctxt() => { | ||
(lhs, rhs, lt, false) | ||
}, | ||
_ => return, | ||
} | ||
&& let typeck = cx.typeck_results() | ||
&& let ty = typeck.expr_ty(op_lhs) | ||
&& matches!(ty.kind(), ty::Uint(_)) | ||
&& ty == typeck.expr_ty(op_rhs) | ||
&& ty == typeck.expr_ty(other) | ||
&& !in_external_macro(cx.tcx.sess, expr.span) | ||
&& (eq_expr_value(cx, op_lhs, other) || (commutative && eq_expr_value(cx, op_rhs, other))) | ||
{ | ||
span_lint( | ||
cx, | ||
PANICKING_OVERFLOW_CHECKS, | ||
expr.span, | ||
"you are trying to use classic C overflow conditions that will fail in Rust", | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#![warn(clippy::panicking_overflow_checks)] | ||
#![allow(clippy::needless_if)] | ||
|
||
fn test(a: u32, b: u32, c: u32) { | ||
if a + b < a {} //~ panicking_overflow_checks | ||
if a > a + b {} //~ panicking_overflow_checks | ||
if a + b < b {} //~ panicking_overflow_checks | ||
if b > a + b {} //~ panicking_overflow_checks | ||
if a - b > b {} | ||
if b < a - b {} | ||
if a - b > a {} //~ panicking_overflow_checks | ||
if a < a - b {} //~ panicking_overflow_checks | ||
if a + b < c {} | ||
if c > a + b {} | ||
if a - b < c {} | ||
if c > a - b {} | ||
let i = 1.1; | ||
let j = 2.2; | ||
if i + j < i {} | ||
if i - j < i {} | ||
if i > i + j {} | ||
if i - j < i {} | ||
} | ||
|
||
fn main() { | ||
test(1, 2, 3) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
error: you are trying to use classic C overflow conditions that will fail in Rust | ||
--> tests/ui/panicking_overflow_checks.rs:5:8 | ||
| | ||
LL | if a + b < a {} | ||
| ^^^^^^^^^ | ||
| | ||
= note: `-D clippy::panicking-overflow-checks` implied by `-D warnings` | ||
= help: to override `-D warnings` add `#[allow(clippy::panicking_overflow_checks)]` | ||
|
||
error: you are trying to use classic C overflow conditions that will fail in Rust | ||
--> tests/ui/panicking_overflow_checks.rs:6:8 | ||
| | ||
LL | if a > a + b {} | ||
| ^^^^^^^^^ | ||
|
||
error: you are trying to use classic C overflow conditions that will fail in Rust | ||
--> tests/ui/panicking_overflow_checks.rs:7:8 | ||
| | ||
LL | if a + b < b {} | ||
| ^^^^^^^^^ | ||
|
||
error: you are trying to use classic C overflow conditions that will fail in Rust | ||
--> tests/ui/panicking_overflow_checks.rs:8:8 | ||
| | ||
LL | if b > a + b {} | ||
| ^^^^^^^^^ | ||
|
||
error: you are trying to use classic C overflow conditions that will fail in Rust | ||
--> tests/ui/panicking_overflow_checks.rs:11:8 | ||
| | ||
LL | if a - b > a {} | ||
| ^^^^^^^^^ | ||
|
||
error: you are trying to use classic C overflow conditions that will fail in Rust | ||
--> tests/ui/panicking_overflow_checks.rs:12:8 | ||
| | ||
LL | if a < a - b {} | ||
| ^^^^^^^^^ | ||
|
||
error: aborting due to 6 previous errors | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.