Skip to content

Commit eb80bb0

Browse files
committed
new_lint non_reentrant_functions
Signed-off-by: mojave2 <[email protected]>
1 parent af6c9d4 commit eb80bb0

File tree

6 files changed

+110
-0
lines changed

6 files changed

+110
-0
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4782,6 +4782,7 @@ Released 2018-09-13
47824782
[`no_mangle_with_rust_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#no_mangle_with_rust_abi
47834783
[`non_ascii_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_ascii_literal
47844784
[`non_octal_unix_permissions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_octal_unix_permissions
4785+
[`non_reentrant_functions`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_reentrant_functions
47854786
[`non_send_fields_in_send_ty`]: https://rust-lang.github.io/rust-clippy/master/index.html#non_send_fields_in_send_ty
47864787
[`nonminimal_bool`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonminimal_bool
47874788
[`nonsensical_open_options`]: https://rust-lang.github.io/rust-clippy/master/index.html#nonsensical_open_options

clippy_lints/src/declared_lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
471471
crate::non_expressive_names::MANY_SINGLE_CHAR_NAMES_INFO,
472472
crate::non_expressive_names::SIMILAR_NAMES_INFO,
473473
crate::non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS_INFO,
474+
crate::non_reentrant_functions::NON_REENTRANT_FUNCTIONS_INFO,
474475
crate::non_send_fields_in_send_ty::NON_SEND_FIELDS_IN_SEND_TY_INFO,
475476
crate::nonstandard_macro_braces::NONSTANDARD_MACRO_BRACES_INFO,
476477
crate::octal_escapes::OCTAL_ESCAPES_INFO,

clippy_lints/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ mod no_mangle_with_rust_abi;
232232
mod non_copy_const;
233233
mod non_expressive_names;
234234
mod non_octal_unix_permissions;
235+
mod non_reentrant_functions;
235236
mod non_send_fields_in_send_ty;
236237
mod nonstandard_macro_braces;
237238
mod octal_escapes;
@@ -966,6 +967,7 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
966967
store.register_late_pass(move |_| Box::new(guidelines::GuidelineLints::new(mem_unsafe_functions.clone())));
967968
store.register_late_pass(|_| Box::new(unsafe_block_in_proc_macro::UnsafeBlockInProcMacro::new()));
968969
store.register_early_pass(|| Box::new(implicit_abi::ImplicitAbi));
970+
store.register_early_pass(|| Box::new(non_reentrant_functions::NonReentrantFunctions));
969971
// add lints here, do not remove this comment, it's used in `new_lint`
970972
}
971973

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
use clippy_utils::diagnostics::span_lint;
2+
use rustc_ast::ast::{Expr, ExprKind, Path};
3+
use rustc_lint::{EarlyContext, EarlyLintPass};
4+
use rustc_session::{declare_lint_pass, declare_tool_lint};
5+
6+
declare_clippy_lint! {
7+
/// ### What it does
8+
///
9+
/// ### Why is this bad?
10+
///
11+
/// ### Example
12+
/// ```rust
13+
/// // example code where clippy issues a warning
14+
/// ```
15+
/// Use instead:
16+
/// ```rust
17+
/// // example code which does not raise clippy warning
18+
/// ```
19+
#[clippy::version = "1.70.0"]
20+
pub NON_REENTRANT_FUNCTIONS,
21+
nursery,
22+
"this function is a non-reentrant-function"
23+
}
24+
declare_lint_pass!(NonReentrantFunctions => [NON_REENTRANT_FUNCTIONS]);
25+
26+
impl EarlyLintPass for NonReentrantFunctions {
27+
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
28+
if expr.span.from_expansion() {
29+
return;
30+
}
31+
32+
let msg: &str = "consider using the reentrant version of the function";
33+
34+
match expr.kind {
35+
ExprKind::Call(ref func, _) => {
36+
if is_reentrant_fn(func) {
37+
span_lint(cx, NON_REENTRANT_FUNCTIONS, expr.span, msg);
38+
}
39+
},
40+
_ => {},
41+
}
42+
}
43+
}
44+
45+
fn is_reentrant_fn(func: &Expr) -> bool {
46+
match &func.kind {
47+
ExprKind::Path(_, Path { segments, .. }) => {
48+
let seg = segments.iter().last().unwrap();
49+
let ident = format!("{:?}", seg.ident);
50+
check_reentrant_by_fn_name(&ident)
51+
},
52+
_ => false,
53+
}
54+
}
55+
56+
fn check_reentrant_by_fn_name(func: &str) -> bool {
57+
let name = func.split("#").next().unwrap();
58+
name == "strtok" || name == "localtime"
59+
}

tests/ui/non_reentrant_functions.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
#![warn(clippy::non_reentrant_functions)]
2+
#![feature(rustc_private)]
3+
extern crate libc;
4+
5+
#[allow(unused)]
6+
use libc::{c_char, localtime, strtok, time_t};
7+
use std::ffi::{CStr, CString};
8+
9+
fn main() {
10+
// test code goes here
11+
unsafe {
12+
let _tm = localtime(&0i64 as *const time_t);
13+
}
14+
15+
let string = CString::new("welcome-to-rust").unwrap();
16+
let string = string.as_ptr() as *mut c_char;
17+
let delim = CString::new(" - ").unwrap();
18+
let delim = delim.as_ptr();
19+
20+
let mut token = unsafe { strtok(string, delim) };
21+
while !token.is_null() {
22+
println!("{:?}", unsafe { CStr::from_ptr(token) });
23+
token = unsafe { strtok(std::ptr::null_mut(), delim) };
24+
}
25+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: consider using the reentrant version of the function
2+
--> $DIR/non_reentrant_functions.rs:12:19
3+
|
4+
LL | let _tm = localtime(&0i64 as *const time_t);
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `-D clippy::non-reentrant-functions` implied by `-D warnings`
8+
9+
error: consider using the reentrant version of the function
10+
--> $DIR/non_reentrant_functions.rs:20:30
11+
|
12+
LL | let mut token = unsafe { strtok(string, delim) };
13+
| ^^^^^^^^^^^^^^^^^^^^^
14+
15+
error: consider using the reentrant version of the function
16+
--> $DIR/non_reentrant_functions.rs:23:26
17+
|
18+
LL | token = unsafe { strtok(std::ptr::null_mut(), delim) };
19+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
20+
21+
error: aborting due to 3 previous errors
22+

0 commit comments

Comments
 (0)