Add invalid_from_utf8 analogous to invalid_from_utf8_unchecked
This commit is contained in:
parent
a0612d90b0
commit
7f99c7d3e6
7 changed files with 169 additions and 21 deletions
|
|
@ -304,6 +304,10 @@ lint_improper_ctypes_union_layout_help = consider adding a `#[repr(C)]` or `#[re
|
|||
lint_improper_ctypes_union_layout_reason = this union has unspecified layout
|
||||
lint_improper_ctypes_union_non_exhaustive = this union is non-exhaustive
|
||||
|
||||
# FIXME: we should ordinalize $valid_up_to when we add support for doing so
|
||||
lint_invalid_from_utf8_checked = calls to `{$method}` with a invalid literal always return an error
|
||||
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
|
||||
|
||||
# FIXME: we should ordinalize $valid_up_to when we add support for doing so
|
||||
lint_invalid_from_utf8_unchecked = calls to `{$method}` with a invalid literal are undefined behavior
|
||||
.label = the literal was valid UTF-8 up to the {$valid_up_to} bytes
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use rustc_hir::{Expr, ExprKind};
|
|||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::sym;
|
||||
|
||||
use crate::lints::InvalidFromUtf8UncheckedDiag;
|
||||
use crate::lints::InvalidFromUtf8Diag;
|
||||
use crate::{LateContext, LateLintPass, LintContext};
|
||||
|
||||
declare_lint! {
|
||||
|
|
@ -33,7 +33,30 @@ declare_lint! {
|
|||
"using a non UTF-8 literal in `std::str::from_utf8_unchecked`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(InvalidFromUtf8 => [INVALID_FROM_UTF8_UNCHECKED]);
|
||||
declare_lint! {
|
||||
/// The `invalid_from_utf8` lint checks for calls to
|
||||
/// `std::str::from_utf8` and `std::str::from_utf8_mut`
|
||||
/// with an invalid UTF-8 literal.
|
||||
///
|
||||
/// ### Example
|
||||
///
|
||||
/// ```rust
|
||||
/// # #[allow(unused)]
|
||||
/// std::str::from_utf8(b"Ru\x82st");
|
||||
/// ```
|
||||
///
|
||||
/// {{produces}}
|
||||
///
|
||||
/// ### Explanation
|
||||
///
|
||||
/// Trying to create such a `str` would always return an error as per documentation
|
||||
/// for `std::str::from_utf8` and `std::str::from_utf8_mut`.
|
||||
pub INVALID_FROM_UTF8,
|
||||
Warn,
|
||||
"using a non UTF-8 literal in `std::str::from_utf8`"
|
||||
}
|
||||
|
||||
declare_lint_pass!(InvalidFromUtf8 => [INVALID_FROM_UTF8_UNCHECKED, INVALID_FROM_UTF8]);
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
|
||||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
|
||||
|
|
@ -41,15 +64,25 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
|
|||
&& let ExprKind::Path(ref qpath) = path.kind
|
||||
&& let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
|
||||
&& let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
|
||||
&& [sym::str_from_utf8_unchecked, sym::str_from_utf8_unchecked_mut].contains(&diag_item)
|
||||
&& [sym::str_from_utf8, sym::str_from_utf8_mut,
|
||||
sym::str_from_utf8_unchecked, sym::str_from_utf8_unchecked_mut].contains(&diag_item)
|
||||
{
|
||||
let lint = |utf8_error: Utf8Error| {
|
||||
let label = arg.span;
|
||||
let method = diag_item.as_str().strip_prefix("str_").unwrap();
|
||||
cx.emit_spanned_lint(INVALID_FROM_UTF8_UNCHECKED, expr.span, InvalidFromUtf8UncheckedDiag {
|
||||
method: format!("std::str::{method}"),
|
||||
valid_up_to: utf8_error.valid_up_to(),
|
||||
label: arg.span,
|
||||
})
|
||||
let method = format!("std::str::{method}");
|
||||
let valid_up_to = utf8_error.valid_up_to();
|
||||
let is_unchecked_variant = diag_item.as_str().contains("unchecked");
|
||||
|
||||
cx.emit_spanned_lint(
|
||||
if is_unchecked_variant { INVALID_FROM_UTF8_UNCHECKED } else { INVALID_FROM_UTF8 },
|
||||
expr.span,
|
||||
if is_unchecked_variant {
|
||||
InvalidFromUtf8Diag::Unchecked { method, valid_up_to, label }
|
||||
} else {
|
||||
InvalidFromUtf8Diag::Checked { method, valid_up_to, label }
|
||||
}
|
||||
)
|
||||
};
|
||||
|
||||
match &arg.kind {
|
||||
|
|
|
|||
|
|
@ -701,12 +701,21 @@ pub struct ForgetCopyDiag<'a> {
|
|||
|
||||
// invalid_from_utf8.rs
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(lint_invalid_from_utf8_unchecked)]
|
||||
pub struct InvalidFromUtf8UncheckedDiag {
|
||||
pub method: String,
|
||||
pub valid_up_to: usize,
|
||||
#[label]
|
||||
pub label: Span,
|
||||
pub enum InvalidFromUtf8Diag {
|
||||
#[diag(lint_invalid_from_utf8_unchecked)]
|
||||
Unchecked {
|
||||
method: String,
|
||||
valid_up_to: usize,
|
||||
#[label]
|
||||
label: Span,
|
||||
},
|
||||
#[diag(lint_invalid_from_utf8_checked)]
|
||||
Checked {
|
||||
method: String,
|
||||
valid_up_to: usize,
|
||||
#[label]
|
||||
label: Span,
|
||||
},
|
||||
}
|
||||
|
||||
// hidden_unicode_codepoints.rs
|
||||
|
|
|
|||
|
|
@ -1454,6 +1454,8 @@ symbols! {
|
|||
stop_after_dataflow,
|
||||
store,
|
||||
str,
|
||||
str_from_utf8,
|
||||
str_from_utf8_mut,
|
||||
str_from_utf8_unchecked,
|
||||
str_from_utf8_unchecked_mut,
|
||||
str_split_whitespace,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue