Skip to content

Commit 45d24fd

Browse files
committed
Auto merge of #4425 - mikerite:4375, r=flip1995
Fix `temporary_cstring_as_ptr` false negative Fixes #4375. Changes the check to test when `.unwrap().as_ptr()` is called on any `Result<CString, _>` as suggested by @flip1995 (#4375 (comment)). changelog: Fix `temporary_cstring_as_ptr` false negative
2 parents 460e265 + 59893bc commit 45d24fd

File tree

4 files changed

+45
-15
lines changed

4 files changed

+45
-15
lines changed

clippy_lints/src/methods/mod.rs

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ use std::iter;
88
use if_chain::if_chain;
99
use matches::matches;
1010
use rustc::hir;
11-
use rustc::hir::def::{DefKind, Res};
1211
use rustc::hir::intravisit::{self, Visitor};
1312
use rustc::lint::{in_external_macro, LateContext, LateLintPass, Lint, LintArray, LintContext, LintPass};
1413
use rustc::ty::{self, Predicate, Ty};
@@ -1668,13 +1667,12 @@ fn lint_extend(cx: &LateContext<'_, '_>, expr: &hir::Expr, args: &[hir::Expr]) {
16681667
}
16691668
}
16701669

1671-
fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, new: &hir::Expr, unwrap: &hir::Expr) {
1670+
fn lint_cstring_as_ptr(cx: &LateContext<'_, '_>, expr: &hir::Expr, source: &hir::Expr, unwrap: &hir::Expr) {
16721671
if_chain! {
1673-
if let hir::ExprKind::Call(ref fun, ref args) = new.node;
1674-
if args.len() == 1;
1675-
if let hir::ExprKind::Path(ref path) = fun.node;
1676-
if let Res::Def(DefKind::Method, did) = cx.tables.qpath_res(path, fun.hir_id);
1677-
if match_def_path(cx, did, &paths::CSTRING_NEW);
1672+
let source_type = cx.tables.expr_ty(source);
1673+
if let ty::Adt(def, substs) = source_type.sty;
1674+
if match_def_path(cx, def.did, &paths::RESULT);
1675+
if match_type(cx, substs.type_at(0), &paths::CSTRING);
16781676
then {
16791677
span_lint_and_then(
16801678
cx,

clippy_lints/src/utils/paths.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub const CLONE_TRAIT_METHOD: [&str; 4] = ["core", "clone", "Clone", "clone"];
1717
pub const CMP_MAX: [&str; 3] = ["core", "cmp", "max"];
1818
pub const CMP_MIN: [&str; 3] = ["core", "cmp", "min"];
1919
pub const COW: [&str; 3] = ["alloc", "borrow", "Cow"];
20-
pub const CSTRING_NEW: [&str; 5] = ["std", "ffi", "c_str", "CString", "new"];
20+
pub const CSTRING: [&str; 4] = ["std", "ffi", "c_str", "CString"];
2121
pub const DEFAULT_TRAIT: [&str; 3] = ["core", "default", "Default"];
2222
pub const DEFAULT_TRAIT_METHOD: [&str; 4] = ["core", "default", "Default", "default"];
2323
pub const DEREF_TRAIT_METHOD: [&str; 5] = ["core", "ops", "deref", "Deref", "deref"];

tests/ui/cstring.rs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,24 @@
1+
#![deny(clippy::temporary_cstring_as_ptr)]
2+
13
fn main() {}
24

3-
#[allow(clippy::result_unwrap_used)]
45
fn temporary_cstring() {
56
use std::ffi::CString;
67

78
CString::new("foo").unwrap().as_ptr();
89
CString::new("foo").expect("dummy").as_ptr();
910
}
11+
12+
mod issue4375 {
13+
use std::ffi::CString;
14+
use std::os::raw::c_char;
15+
16+
extern "C" {
17+
fn foo(data: *const c_char);
18+
}
19+
20+
pub fn bar(v: &[u8]) {
21+
let cstr = CString::new(v);
22+
unsafe { foo(cstr.unwrap().as_ptr()) }
23+
}
24+
}

tests/ui/cstring.stderr

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,46 @@
11
error: you are getting the inner pointer of a temporary `CString`
2-
--> $DIR/cstring.rs:7:5
2+
--> $DIR/cstring.rs:8:5
33
|
44
LL | CString::new("foo").unwrap().as_ptr();
55
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
66
|
7-
= note: `#[deny(clippy::temporary_cstring_as_ptr)]` on by default
7+
note: lint level defined here
8+
--> $DIR/cstring.rs:1:9
9+
|
10+
LL | #![deny(clippy::temporary_cstring_as_ptr)]
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
812
= note: that pointer will be invalid outside this expression
913
help: assign the `CString` to a variable to extend its lifetime
10-
--> $DIR/cstring.rs:7:5
14+
--> $DIR/cstring.rs:8:5
1115
|
1216
LL | CString::new("foo").unwrap().as_ptr();
1317
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1418

1519
error: you are getting the inner pointer of a temporary `CString`
16-
--> $DIR/cstring.rs:8:5
20+
--> $DIR/cstring.rs:9:5
1721
|
1822
LL | CString::new("foo").expect("dummy").as_ptr();
1923
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2024
|
2125
= note: that pointer will be invalid outside this expression
2226
help: assign the `CString` to a variable to extend its lifetime
23-
--> $DIR/cstring.rs:8:5
27+
--> $DIR/cstring.rs:9:5
2428
|
2529
LL | CString::new("foo").expect("dummy").as_ptr();
2630
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
2731

28-
error: aborting due to 2 previous errors
32+
error: you are getting the inner pointer of a temporary `CString`
33+
--> $DIR/cstring.rs:22:22
34+
|
35+
LL | unsafe { foo(cstr.unwrap().as_ptr()) }
36+
| ^^^^^^^^^^^^^^^^^^^^^^
37+
|
38+
= note: that pointer will be invalid outside this expression
39+
help: assign the `CString` to a variable to extend its lifetime
40+
--> $DIR/cstring.rs:22:22
41+
|
42+
LL | unsafe { foo(cstr.unwrap().as_ptr()) }
43+
| ^^^^^^^^^^^^^
44+
45+
error: aborting due to 3 previous errors
2946

0 commit comments

Comments
 (0)