diff options
| -rw-r--r-- | compiler/rustc_lint/src/methods.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_span/src/symbol.rs | 1 | ||||
| -rw-r--r-- | library/std/src/ffi/c_str.rs | 2 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-temporary-cstring-as-param.rs | 10 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-temporary-cstring-as-param.stderr | 19 | ||||
| -rw-r--r-- | src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr | 6 |
6 files changed, 44 insertions, 13 deletions
diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index f1e44fbe2a2..3852cc4f298 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -3,10 +3,7 @@ use crate::LateLintPass; use crate::LintContext; use rustc_hir::{Expr, ExprKind, PathSegment}; use rustc_middle::ty; -use rustc_span::{ - symbol::{sym, Symbol}, - ExpnKind, Span, -}; +use rustc_span::{symbol::sym, ExpnKind, Span}; declare_lint! { pub TEMPORARY_CSTRING_AS_PTR, @@ -59,8 +56,6 @@ impl<'tcx> LateLintPass<'tcx> for TemporaryCStringAsPtr { } } -const CSTRING_PATH: [Symbol; 4] = [sym::std, sym::ffi, sym::c_str, sym::CString]; - fn lint_cstring_as_ptr( cx: &LateContext<'_>, as_ptr_span: Span, @@ -68,19 +63,21 @@ fn lint_cstring_as_ptr( unwrap: &rustc_hir::Expr<'_>, ) { let source_type = cx.typeck_results().expr_ty(source); - if let ty::Adt(def, substs) = source_type.kind { + if let ty::Adt(def, substs) = source_type.kind() { if cx.tcx.is_diagnostic_item(sym::result_type, def.did) { - if let ty::Adt(adt, _) = substs.type_at(0).kind { - if cx.match_def_path(adt.did, &CSTRING_PATH) { + if let ty::Adt(adt, _) = substs.type_at(0).kind() { + if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did) { cx.struct_span_lint(TEMPORARY_CSTRING_AS_PTR, as_ptr_span, |diag| { let mut diag = diag .build("getting the inner pointer of a temporary `CString`"); diag.span_label(as_ptr_span, "this pointer will be invalid"); diag.span_label( unwrap.span, - "this `CString` is deallocated at the end of the expression, bind it to a variable to extend its lifetime", + "this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime", ); - diag.note("pointers do not have a lifetime; when calling `as_ptr` the `CString` is deallocated because nothing is referencing it as far as the type system is concerned"); + diag.note("pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement..."); + diag.note("...because nothing is referencing it as far as the type system is concerned"); + diag.help("for more information, see https://doc.rust-lang.org/reference/destructors.html"); diag.emit(); }); } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 38539643416..10d47b824bc 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -400,6 +400,7 @@ symbols! { crate_type, crate_visibility_modifier, crt_dash_static: "crt-static", + cstring_type, ctlz, ctlz_nonzero, ctpop, diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index a9ab0d1d83b..1cfd73863a6 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -109,7 +109,9 @@ use crate::sys; /// documentation of `CString` before use, as improper ownership management /// of `CString` instances can lead to invalid memory accesses, memory leaks, /// and other memory errors. + #[derive(PartialEq, PartialOrd, Eq, Ord, Hash, Clone)] +#[cfg_attr(not(test), rustc_diagnostic_item = "cstring_type")] #[stable(feature = "rust1", since = "1.0.0")] pub struct CString { // Invariant 1: the slice ends with a zero byte and has a length of at least one. diff --git a/src/test/ui/lint/lint-temporary-cstring-as-param.rs b/src/test/ui/lint/lint-temporary-cstring-as-param.rs new file mode 100644 index 00000000000..197b7fd704f --- /dev/null +++ b/src/test/ui/lint/lint-temporary-cstring-as-param.rs @@ -0,0 +1,10 @@ +// ignore-tidy-linelength +#![deny(temporary_cstring_as_ptr)] + +use std::ffi::CString; + +fn some_function(data: *const i8) {} + +fn main() { + some_function(CString::new("").unwrap().as_ptr()); //~ ERROR getting the inner pointer of a temporary `CString` +} diff --git a/src/test/ui/lint/lint-temporary-cstring-as-param.stderr b/src/test/ui/lint/lint-temporary-cstring-as-param.stderr new file mode 100644 index 00000000000..1e0d0d954dc --- /dev/null +++ b/src/test/ui/lint/lint-temporary-cstring-as-param.stderr @@ -0,0 +1,19 @@ +error: getting the inner pointer of a temporary `CString` + --> $DIR/lint-temporary-cstring-as-param.rs:9:45 + | +LL | some_function(CString::new("").unwrap().as_ptr()); + | ------------------------- ^^^^^^ this pointer will be invalid + | | + | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime + | +note: the lint level is defined here + --> $DIR/lint-temporary-cstring-as-param.rs:2:9 + | +LL | #![deny(temporary_cstring_as_ptr)] + | ^^^^^^^^^^^^^^^^^^^^^^^^ + = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement... + = note: ...because nothing is referencing it as far as the type system is concerned + = help: for more information, see https://doc.rust-lang.org/reference/destructors.html + +error: aborting due to previous error + diff --git a/src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr b/src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr index ee06bfc2fad..8fca03b49df 100644 --- a/src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr +++ b/src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr @@ -4,14 +4,16 @@ error: getting the inner pointer of a temporary `CString` LL | let s = CString::new("some text").unwrap().as_ptr(); | ---------------------------------- ^^^^^^ this pointer will be invalid | | - | this `CString` is deallocated at the end of the expression, bind it to a variable to extend its lifetime + | this `CString` is deallocated at the end of the statement, bind it to a variable to extend its lifetime | note: the lint level is defined here --> $DIR/lint-temporary-cstring-as-ptr.rs:2:9 | LL | #![deny(temporary_cstring_as_ptr)] | ^^^^^^^^^^^^^^^^^^^^^^^^ - = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` is deallocated because nothing is referencing it as far as the type system is concerned + = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement... + = note: ...because nothing is referencing it as far as the type system is concerned + = help: for more information, see https://doc.rust-lang.org/reference/destructors.html error: aborting due to previous error |
