Skip to content

Commit d5a1eff

Browse files
authored
Merge pull request rust-lang#2 from mojave2/dev_stable
new_lint non_reentrant_functions
2 parents af6c9d4 + 9cd4b13 commit d5a1eff

File tree

6 files changed

+120
-0
lines changed

6 files changed

+120
-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: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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+
/// Checks for non-reentrant functions.
9+
///
10+
/// ### Why is this bad?
11+
/// This makes code safer, especially in the context of concurrency.
12+
///
13+
/// ### Example
14+
/// ```rust
15+
/// let _tm = libc::localtime(&0i64 as *const libc::time_t);
16+
/// ```
17+
/// Use instead:
18+
/// ```rust
19+
/// let res = libc::malloc(std::mem::size_of::<libc::tm>());
20+
///
21+
/// libc::locatime_r(&0i64 as *const libc::time_t, res);
22+
/// ```
23+
#[clippy::version = "1.70.0"]
24+
pub NON_REENTRANT_FUNCTIONS,
25+
nursery,
26+
"this function is a non-reentrant-function"
27+
}
28+
declare_lint_pass!(NonReentrantFunctions => [NON_REENTRANT_FUNCTIONS]);
29+
30+
impl EarlyLintPass for NonReentrantFunctions {
31+
fn check_expr(&mut self, cx: &EarlyContext<'_>, expr: &Expr) {
32+
if expr.span.from_expansion() {
33+
return;
34+
}
35+
36+
let msg: &str = "consider using the reentrant version of the function";
37+
38+
if let ExprKind::Call(func, _) = &expr.kind {
39+
if is_reentrant_fn(func) {
40+
span_lint(cx, NON_REENTRANT_FUNCTIONS, expr.span, msg);
41+
}
42+
}
43+
}
44+
}
45+
46+
fn is_reentrant_fn(func: &Expr) -> bool {
47+
match &func.kind {
48+
ExprKind::Path(_, Path { segments, .. }) => {
49+
if segments.len() != 2 || segments[0].ident.name != rustc_span::sym::libc {
50+
return false;
51+
}
52+
matches!(segments[1].ident.as_str(), "strtok" | "localtime")
53+
},
54+
_ => false,
55+
}
56+
}

tests/ui/non_reentrant_functions.rs

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

0 commit comments

Comments
 (0)