-
Notifications
You must be signed in to change notification settings - Fork 0
fix: address lint false positives, UI test diffs, and panic detection edge cases #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
224f621
e98f4c5
8c1ef0c
72a5869
9f1ad5f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -12,6 +12,7 @@ use rustc_hir::{Expr, ExprKind}; | |||||||||||||
| use rustc_lint::{LateContext, LateLintPass, LintContext, LintStore}; | ||||||||||||||
| use rustc_middle::ty::TyCtxt; | ||||||||||||||
| use rustc_session::{Session, declare_lint, declare_lint_pass}; | ||||||||||||||
| use rustc_span::sym; | ||||||||||||||
|
|
||||||||||||||
| declare_lint! { | ||||||||||||||
| pub SECURITY_PANIC_USAGE, | ||||||||||||||
|
|
@@ -21,26 +22,6 @@ declare_lint! { | |||||||||||||
|
|
||||||||||||||
| declare_lint_pass!(SecurityPanicUsage => [SECURITY_PANIC_USAGE]); | ||||||||||||||
|
|
||||||||||||||
| /// Enum representing the different kinds of panic-related constructs that can | ||||||||||||||
| /// be detected by the `SECURITY_PANIC_USAGE` lint, such as calls to `unwrap` | ||||||||||||||
| /// and `expect` methods, as well as calls to panic-related functions in the | ||||||||||||||
| /// standard library. | ||||||||||||||
| #[derive(Debug, Clone, Copy)] | ||||||||||||||
| enum PanicKind { | ||||||||||||||
| Unwrap, | ||||||||||||||
| Expect, | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| impl PanicKind { | ||||||||||||||
| fn from_method(name: &str) -> Option<Self> { | ||||||||||||||
| match name { | ||||||||||||||
| "unwrap" => Some(Self::Unwrap), | ||||||||||||||
| "expect" => Some(Self::Expect), | ||||||||||||||
| _ => None, | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
| } | ||||||||||||||
|
|
||||||||||||||
| /// Enum representing the different panic backends that can be detected by the | ||||||||||||||
| /// `SECURITY_PANIC_USAGE` lint, such as the `panicking` module, the | ||||||||||||||
| /// `panic_fmt` function, the `panic_display` function, the `assert_failed` | ||||||||||||||
|
|
@@ -87,20 +68,29 @@ impl<'tcx> LateLintPass<'tcx> for SecurityPanicUsage { | |||||||||||||
| expression: &'tcx Expr<'tcx>, | ||||||||||||||
| ) { | ||||||||||||||
| // Detect direct calls to `unwrap` and `expect` methods. | ||||||||||||||
| if let ExprKind::MethodCall(segment, _, _, _) = &expression.kind | ||||||||||||||
| && let Some(kind) = | ||||||||||||||
| PanicKind::from_method(segment.ident.name.as_str()) | ||||||||||||||
| // This checks for method calls where the method name is `unwrap` or | ||||||||||||||
| // `expect`, and the method is defined in the local crate (to avoid | ||||||||||||||
| // false positives from external crates). | ||||||||||||||
|
Comment on lines
+71
to
+73
|
||||||||||||||
| if let ExprKind::MethodCall(_, _, _, _) = &expression.kind | ||||||||||||||
| && let Some(def_id) = context | ||||||||||||||
| .typeck_results() | ||||||||||||||
| .type_dependent_def_id(expression.hir_id) | ||||||||||||||
| { | ||||||||||||||
| context.span_lint( | ||||||||||||||
| SECURITY_PANIC_USAGE, | ||||||||||||||
| expression.span, | ||||||||||||||
| |diagnostic: &mut Diag<'_, ()>| { | ||||||||||||||
| diagnostic.primary_message(format!( | ||||||||||||||
| "Call to panic backend `{kind:?}` detected." | ||||||||||||||
| )); | ||||||||||||||
| }, | ||||||||||||||
| ); | ||||||||||||||
| return; | ||||||||||||||
| if context.tcx.is_diagnostic_item(sym::unwrap, def_id) | ||||||||||||||
| || context.tcx.is_diagnostic_item(sym::option_unwrap, def_id) | ||||||||||||||
| || context.tcx.is_diagnostic_item(sym::except, def_id) | ||||||||||||||
|
||||||||||||||
| || context.tcx.is_diagnostic_item(sym::except, def_id) | |
| || context.tcx.is_diagnostic_item(sym::expect, def_id) |
Copilot
AI
Feb 16, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code only checks for sym::unwrap and sym::option_unwrap but may be missing Result::unwrap. The standard library provides diagnostic items for both Option and Result versions of these methods. Consider adding checks for sym::result_unwrap and sym::result_expect (if they exist) to ensure complete coverage of panic-inducing methods on both Option and Result types.
| || context.tcx.is_diagnostic_item(sym::except, def_id) | |
| || context.tcx.is_diagnostic_item(sym::option_expect, def_id) | |
| || context.tcx.is_diagnostic_item(sym::expect, def_id) | |
| || context.tcx.is_diagnostic_item(sym::option_expect, def_id) | |
| || context.tcx.is_diagnostic_item(sym::result_unwrap, def_id) | |
| || context.tcx.is_diagnostic_item(sym::result_expect, def_id) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment "Skip if the expression is from a macro expansion" is inaccurate here. The check
from_expansion()was already performed at lines 99-101. This check is actually filtering out coroutines (async blocks, generators), not macro expansions. The comment should be updated to say something like "Skip coroutines (async blocks, generators) as they have compiler-generated state machines with implicit type annotations."