Skip to content

Commit 38ab3a3

Browse files
authored
Merge pull request rust-lang#1 from J-ZhengLi/dev_stable
add new lints: [`mem_unsafe_functions`], [`unsafe_block_in_proc_macro`] and [`implicit_abi`]
2 parents 83e42a2 + 5ce5313 commit 38ab3a3

24 files changed

+1061
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4532,6 +4532,7 @@ Released 2018-09-13
45324532
[`extend_with_drain`]: https://rust-lang.github.io/rust-clippy/master/index.html#extend_with_drain
45334533
[`extra_unused_lifetimes`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_lifetimes
45344534
[`extra_unused_type_parameters`]: https://rust-lang.github.io/rust-clippy/master/index.html#extra_unused_type_parameters
4535+
[`falliable_memory_allocation`]: https://rust-lang.github.io/rust-clippy/master/index.html#falliable_memory_allocation
45354536
[`fallible_impl_from`]: https://rust-lang.github.io/rust-clippy/master/index.html#fallible_impl_from
45364537
[`field_reassign_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#field_reassign_with_default
45374538
[`filetype_is_file`]: https://rust-lang.github.io/rust-clippy/master/index.html#filetype_is_file
@@ -4579,6 +4580,7 @@ Released 2018-09-13
45794580
[`if_then_some_else_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#if_then_some_else_none
45804581
[`ifs_same_cond`]: https://rust-lang.github.io/rust-clippy/master/index.html#ifs_same_cond
45814582
[`impl_trait_in_params`]: https://rust-lang.github.io/rust-clippy/master/index.html#impl_trait_in_params
4583+
[`implicit_abi`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_abi
45824584
[`implicit_clone`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_clone
45834585
[`implicit_hasher`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_hasher
45844586
[`implicit_return`]: https://rust-lang.github.io/rust-clippy/master/index.html#implicit_return
@@ -4707,6 +4709,7 @@ Released 2018-09-13
47074709
[`mem_replace_option_with_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_option_with_none
47084710
[`mem_replace_with_default`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_default
47094711
[`mem_replace_with_uninit`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_replace_with_uninit
4712+
[`mem_unsafe_functions`]: https://rust-lang.github.io/rust-clippy/master/index.html#mem_unsafe_functions
47104713
[`min_max`]: https://rust-lang.github.io/rust-clippy/master/index.html#min_max
47114714
[`misaligned_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#misaligned_transmute
47124715
[`mismatched_target_os`]: https://rust-lang.github.io/rust-clippy/master/index.html#mismatched_target_os
@@ -4813,6 +4816,7 @@ Released 2018-09-13
48134816
[`partial_pub_fields`]: https://rust-lang.github.io/rust-clippy/master/index.html#partial_pub_fields
48144817
[`partialeq_ne_impl`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_ne_impl
48154818
[`partialeq_to_none`]: https://rust-lang.github.io/rust-clippy/master/index.html#partialeq_to_none
4819+
[`passing_string_to_c_functions`]: https://rust-lang.github.io/rust-clippy/master/index.html#passing_string_to_c_functions
48164820
[`path_buf_push_overwrite`]: https://rust-lang.github.io/rust-clippy/master/index.html#path_buf_push_overwrite
48174821
[`pattern_type_mismatch`]: https://rust-lang.github.io/rust-clippy/master/index.html#pattern_type_mismatch
48184822
[`permissions_set_readonly_false`]: https://rust-lang.github.io/rust-clippy/master/index.html#permissions_set_readonly_false
@@ -5003,13 +5007,15 @@ Released 2018-09-13
50035007
[`unnested_or_patterns`]: https://rust-lang.github.io/rust-clippy/master/index.html#unnested_or_patterns
50045008
[`unreachable`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreachable
50055009
[`unreadable_literal`]: https://rust-lang.github.io/rust-clippy/master/index.html#unreadable_literal
5010+
[`unsafe_block_in_proc_macro`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_block_in_proc_macro
50065011
[`unsafe_derive_deserialize`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_derive_deserialize
50075012
[`unsafe_removed_from_name`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_removed_from_name
50085013
[`unsafe_vector_initialization`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsafe_vector_initialization
50095014
[`unseparated_literal_suffix`]: https://rust-lang.github.io/rust-clippy/master/index.html#unseparated_literal_suffix
50105015
[`unsound_collection_transmute`]: https://rust-lang.github.io/rust-clippy/master/index.html#unsound_collection_transmute
50115016
[`unstable_as_mut_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_mut_slice
50125017
[`unstable_as_slice`]: https://rust-lang.github.io/rust-clippy/master/index.html#unstable_as_slice
5018+
[`untrusted_lib_loading`]: https://rust-lang.github.io/rust-clippy/master/index.html#untrusted_lib_loading
50135019
[`unused_async`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_async
50145020
[`unused_collect`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_collect
50155021
[`unused_format_specs`]: https://rust-lang.github.io/rust-clippy/master/index.html#unused_format_specs

clippy_lints/src/declared_lints.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,9 +191,14 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
191191
crate::functions::TOO_MANY_ARGUMENTS_INFO,
192192
crate::functions::TOO_MANY_LINES_INFO,
193193
crate::future_not_send::FUTURE_NOT_SEND_INFO,
194+
crate::guidelines::FALLIABLE_MEMORY_ALLOCATION_INFO,
195+
crate::guidelines::MEM_UNSAFE_FUNCTIONS_INFO,
196+
crate::guidelines::PASSING_STRING_TO_C_FUNCTIONS_INFO,
197+
crate::guidelines::UNTRUSTED_LIB_LOADING_INFO,
194198
crate::if_let_mutex::IF_LET_MUTEX_INFO,
195199
crate::if_not_else::IF_NOT_ELSE_INFO,
196200
crate::if_then_some_else_none::IF_THEN_SOME_ELSE_NONE_INFO,
201+
crate::implicit_abi::IMPLICIT_ABI_INFO,
197202
crate::implicit_hasher::IMPLICIT_HASHER_INFO,
198203
crate::implicit_return::IMPLICIT_RETURN_INFO,
199204
crate::implicit_saturating_add::IMPLICIT_SATURATING_ADD_INFO,
@@ -628,6 +633,7 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
628633
crate::unnecessary_struct_initialization::UNNECESSARY_STRUCT_INITIALIZATION_INFO,
629634
crate::unnecessary_wraps::UNNECESSARY_WRAPS_INFO,
630635
crate::unnested_or_patterns::UNNESTED_OR_PATTERNS_INFO,
636+
crate::unsafe_block_in_proc_macro::UNSAFE_BLOCK_IN_PROC_MACRO_INFO,
631637
crate::unsafe_removed_from_name::UNSAFE_REMOVED_FROM_NAME_INFO,
632638
crate::unused_async::UNUSED_ASYNC_INFO,
633639
crate::unused_io_amount::UNUSED_IO_AMOUNT_INFO,
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
use clippy_utils::diagnostics::span_lint_and_help;
2+
use if_chain::if_chain;
3+
use rustc_hir::def::Res;
4+
use rustc_hir::def_id::DefIdSet;
5+
use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath};
6+
use rustc_lint::LateContext;
7+
8+
use super::MEM_UNSAFE_FUNCTIONS;
9+
10+
/// Check extern function definitions.
11+
///
12+
/// The main purpose of this function is to load `def_ids` of declared external functions.
13+
pub(super) fn check_foreign_item(item: &Item<'_>, blacklist: &[String], blacklist_ids: &mut DefIdSet) {
14+
if let ItemKind::ForeignMod { items, .. } = item.kind {
15+
for f_item in items {
16+
if blacklist.contains(&f_item.ident.as_str().to_string()) {
17+
let f_did = f_item.id.hir_id().owner.def_id.to_def_id();
18+
blacklist_ids.insert(f_did);
19+
}
20+
}
21+
}
22+
}
23+
24+
/// Check function call expression
25+
///
26+
/// Will lint if the name of called function was blacklisted by the configuration.
27+
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, blacklist_ids: &DefIdSet) {
28+
if_chain! {
29+
if let ExprKind::Call(fn_expr, _) = &expr.kind;
30+
if let ExprKind::Path(qpath) = &fn_expr.kind;
31+
if let QPath::Resolved(_, path) = qpath;
32+
if let Res::Def(_, did) = path.res;
33+
if blacklist_ids.contains(&did);
34+
then {
35+
span_lint_and_help(
36+
cx,
37+
MEM_UNSAFE_FUNCTIONS,
38+
fn_expr.span,
39+
"use of potentially dangerous memory manipulation function",
40+
None,
41+
"consider using its safe version",
42+
);
43+
}
44+
}
45+
}

clippy_lints/src/guidelines/mod.rs

Lines changed: 159 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
mod falliable_memory_allocation;
2+
mod mem_unsafe_functions;
3+
mod passing_string_to_c_functions;
4+
mod untrusted_lib_loading;
5+
6+
use clippy_utils::def_path_def_ids;
7+
use rustc_hir as hir;
8+
use rustc_hir::def_id::{DefId, DefIdSet};
9+
use rustc_hir::intravisit;
10+
use rustc_lint::{LateContext, LateLintPass};
11+
use rustc_session::{declare_tool_lint, impl_lint_pass};
12+
use rustc_span::def_id::LocalDefId;
13+
use rustc_span::Span;
14+
15+
declare_clippy_lint! {
16+
/// ### What it does
17+
/// Checks for direct usage of external functions that modify memory
18+
/// without concerning about memory safety, such as `memcpy`, `strcpy`, `strcat` etc.
19+
///
20+
/// ### Why is this bad?
21+
/// These function can be dangerous when used incorrectly,
22+
/// which could potentially introduce vulnerablities such as buffer overflow to the software.
23+
///
24+
/// ### Example
25+
/// ```rust
26+
/// extern "C" {
27+
/// fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void;
28+
/// }
29+
/// let ptr = unsafe { memcpy(dest, src, size); }
30+
/// // Or use via libc
31+
/// let ptr = unsafe { libc::memcpy(dest, src, size); }
32+
#[clippy::version = "1.70.0"]
33+
pub MEM_UNSAFE_FUNCTIONS,
34+
nursery,
35+
"use of potentially dangerous external functions"
36+
}
37+
38+
declare_clippy_lint! {
39+
/// ### What it does
40+
///
41+
/// ### Why is this bad?
42+
///
43+
/// ### Example
44+
/// ```rust
45+
/// // example code where clippy issues a warning
46+
/// ```
47+
/// Use instead:
48+
/// ```rust
49+
/// // example code which does not raise clippy warning
50+
/// ```
51+
#[clippy::version = "1.70.0"]
52+
pub UNTRUSTED_LIB_LOADING,
53+
nursery,
54+
"attempt to load dynamic library from untrusted source"
55+
}
56+
57+
declare_clippy_lint! {
58+
/// ### What it does
59+
///
60+
/// ### Why is this bad?
61+
///
62+
/// ### Example
63+
/// ```rust
64+
/// // example code where clippy issues a warning
65+
/// ```
66+
/// Use instead:
67+
/// ```rust
68+
/// // example code which does not raise clippy warning
69+
/// ```
70+
#[clippy::version = "1.70.0"]
71+
pub PASSING_STRING_TO_C_FUNCTIONS,
72+
nursery,
73+
"passing string or str to extern C function"
74+
}
75+
76+
declare_clippy_lint! {
77+
/// ### What it does
78+
///
79+
/// ### Why is this bad?
80+
///
81+
/// ### Example
82+
/// ```rust
83+
/// // example code where clippy issues a warning
84+
/// ```
85+
/// Use instead:
86+
/// ```rust
87+
/// // example code which does not raise clippy warning
88+
/// ```
89+
#[clippy::version = "1.70.0"]
90+
pub FALLIABLE_MEMORY_ALLOCATION,
91+
nursery,
92+
"memory allocation without checking arguments and result"
93+
}
94+
95+
#[derive(Clone, Default)]
96+
pub struct GuidelineLints {
97+
mem_uns_fns: Vec<String>,
98+
mem_uns_fns_ty_ids: DefIdSet,
99+
}
100+
101+
impl GuidelineLints {
102+
pub fn new(mem_uns_fns: Vec<String>) -> Self {
103+
Self {
104+
mem_uns_fns,
105+
mem_uns_fns_ty_ids: DefIdSet::new(),
106+
}
107+
}
108+
}
109+
110+
impl_lint_pass!(GuidelineLints => [
111+
MEM_UNSAFE_FUNCTIONS,
112+
UNTRUSTED_LIB_LOADING,
113+
PASSING_STRING_TO_C_FUNCTIONS,
114+
FALLIABLE_MEMORY_ALLOCATION,
115+
]);
116+
117+
impl<'tcx> LateLintPass<'tcx> for GuidelineLints {
118+
fn check_fn(
119+
&mut self,
120+
_cx: &LateContext<'tcx>,
121+
_kind: intravisit::FnKind<'tcx>,
122+
_decl: &'tcx hir::FnDecl<'_>,
123+
_body: &'tcx hir::Body<'_>,
124+
_span: Span,
125+
_def_id: LocalDefId,
126+
) {
127+
}
128+
129+
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
130+
// Resolve function names to def_ids from configuration
131+
for uns_fns in &self.mem_uns_fns {
132+
// Path like function names such as `libc::foo` or `aa::bb::cc::bar`,
133+
// this only works with dependencies.
134+
if uns_fns.contains("::") {
135+
let path: Vec<&str> = uns_fns.split("::").collect();
136+
for did in def_path_def_ids(cx, path.as_slice()) {
137+
self.mem_uns_fns_ty_ids.insert(did);
138+
}
139+
}
140+
// Plain function names, then we should take its libc variant into account
141+
else if let Some(did) = libc_fn_def_id(cx, uns_fns) {
142+
self.mem_uns_fns_ty_ids.insert(did);
143+
}
144+
}
145+
}
146+
147+
fn check_item(&mut self, _cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) {
148+
mem_unsafe_functions::check_foreign_item(item, &self.mem_uns_fns, &mut self.mem_uns_fns_ty_ids);
149+
}
150+
151+
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) {
152+
mem_unsafe_functions::check(cx, expr, &self.mem_uns_fns_ty_ids);
153+
}
154+
}
155+
156+
fn libc_fn_def_id(cx: &LateContext<'_>, fn_name: &str) -> Option<DefId> {
157+
let path = &["libc", fn_name];
158+
def_path_def_ids(cx, path).next()
159+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

clippy_lints/src/implicit_abi.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use clippy_utils::diagnostics::span_lint_and_sugg;
2+
use rustc_ast::ast::{Item, ItemKind};
3+
use rustc_errors::Applicability;
4+
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
5+
use rustc_session::{declare_lint_pass, declare_tool_lint};
6+
7+
declare_clippy_lint! {
8+
/// ### What it does
9+
/// Checks the external block without explicitly lable its ABI.
10+
///
11+
/// ### Why is this bad?
12+
/// Implicit ABI has negative impact on code readability.
13+
///
14+
/// ### Example
15+
/// ```rust
16+
/// extern {
17+
/// fn c_function();
18+
/// }
19+
/// ```
20+
/// Use instead:
21+
/// ```rust
22+
/// extern "C" {
23+
/// fn c_function();
24+
/// }
25+
/// ```
26+
#[clippy::version = "1.70.0"]
27+
pub IMPLICIT_ABI,
28+
restriction,
29+
"external block with implicit ABI"
30+
}
31+
32+
declare_lint_pass!(ImplicitAbi => [IMPLICIT_ABI]);
33+
34+
impl EarlyLintPass for ImplicitAbi {
35+
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
36+
if let ItemKind::ForeignMod(fm) = &item.kind {
37+
if fm.abi.is_none() {
38+
let extern_span = cx.sess().source_map().span_until_whitespace(item.span);
39+
span_lint_and_sugg(
40+
cx,
41+
IMPLICIT_ABI,
42+
extern_span,
43+
"missing ABI label on extern block",
44+
"explicitly states ABI instead",
45+
"extern \"C\"".to_string(),
46+
Applicability::MachineApplicable,
47+
);
48+
}
49+
}
50+
}
51+
}

clippy_lints/src/lib.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,9 +138,11 @@ mod from_raw_with_void_ptr;
138138
mod from_str_radix_10;
139139
mod functions;
140140
mod future_not_send;
141+
mod guidelines;
141142
mod if_let_mutex;
142143
mod if_not_else;
143144
mod if_then_some_else_none;
145+
mod implicit_abi;
144146
mod implicit_hasher;
145147
mod implicit_return;
146148
mod implicit_saturating_add;
@@ -309,6 +311,7 @@ mod unnecessary_self_imports;
309311
mod unnecessary_struct_initialization;
310312
mod unnecessary_wraps;
311313
mod unnested_or_patterns;
314+
mod unsafe_block_in_proc_macro;
312315
mod unsafe_removed_from_name;
313316
mod unused_async;
314317
mod unused_io_amount;
@@ -959,6 +962,10 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
959962
store.register_late_pass(|_| Box::new(tests_outside_test_module::TestsOutsideTestModule));
960963
store.register_late_pass(|_| Box::new(manual_slice_size_calculation::ManualSliceSizeCalculation));
961964
store.register_early_pass(|| Box::new(suspicious_doc_comments::SuspiciousDocComments));
965+
let mem_unsafe_functions = conf.mem_unsafe_functions.clone();
966+
store.register_late_pass(move |_| Box::new(guidelines::GuidelineLints::new(mem_unsafe_functions.clone())));
967+
store.register_late_pass(|_| Box::new(unsafe_block_in_proc_macro::UnsafeBlockInProcMacro::new()));
968+
store.register_early_pass(|| Box::new(implicit_abi::ImplicitAbi));
962969
// add lints here, do not remove this comment, it's used in `new_lint`
963970
}
964971

0 commit comments

Comments
 (0)