diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs index 3852cc4f298..2fad02bf883 100644 --- a/compiler/rustc_lint/src/methods.rs +++ b/compiler/rustc_lint/src/methods.rs @@ -6,6 +6,25 @@ use rustc_middle::ty; use rustc_span::{symbol::sym, ExpnKind, Span}; declare_lint! { + /// The `temporary_cstring_as_ptr` lint detects getting the inner pointer of + /// a temporary `CString`. + /// + /// ### Example + /// + /// ```rust + /// # #![allow(unused)] + /// let c_str = CString::new("foo").unwrap().as_ptr(); + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// The inner pointer of a `CString` lives only as long as the `CString` it + /// points to. Getting the inner pointer of a *temporary* `CString` allows the `CString` + /// to be dropped at the end of the statement, as it is not being referenced as far as the typesystem + /// is concerned. This means outside of the statement the pointer will point to freed memory, which + /// causes undefined behavior if the pointer is later dereferenced. pub TEMPORARY_CSTRING_AS_PTR, Warn, "detects getting the inner pointer of a temporary `CString`" @@ -75,8 +94,7 @@ fn lint_cstring_as_ptr( unwrap.span, "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` 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.note("pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement 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/src/test/ui/lint/lint-temporary-cstring-as-param.stderr b/src/test/ui/lint/lint-temporary-cstring-as-param.stderr index 1e0d0d954dc..b30ebd5e409 100644 --- a/src/test/ui/lint/lint-temporary-cstring-as-param.stderr +++ b/src/test/ui/lint/lint-temporary-cstring-as-param.stderr @@ -11,8 +11,7 @@ note: the lint level is defined here | 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 + = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement 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.rs b/src/test/ui/lint/lint-temporary-cstring-as-ptr.rs index 73a9d6677c7..e463f84c48d 100644 --- a/src/test/ui/lint/lint-temporary-cstring-as-ptr.rs +++ b/src/test/ui/lint/lint-temporary-cstring-as-ptr.rs @@ -1,4 +1,5 @@ // ignore-tidy-linelength +// this program is not technically incorrect, but is an obscure enough style to be worth linting #![deny(temporary_cstring_as_ptr)] use std::ffi::CString; 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 8fca03b49df..009cfe343a6 100644 --- a/src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr +++ b/src/test/ui/lint/lint-temporary-cstring-as-ptr.stderr @@ -1,5 +1,5 @@ error: getting the inner pointer of a temporary `CString` - --> $DIR/lint-temporary-cstring-as-ptr.rs:7:48 + --> $DIR/lint-temporary-cstring-as-ptr.rs:8:48 | LL | let s = CString::new("some text").unwrap().as_ptr(); | ---------------------------------- ^^^^^^ this pointer will be invalid @@ -7,12 +7,11 @@ LL | let s = CString::new("some text").unwrap().as_ptr(); | 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 + --> $DIR/lint-temporary-cstring-as-ptr.rs:3: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 + = note: pointers do not have a lifetime; when calling `as_ptr` the `CString` will be deallocated at the end of the statement 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