forked from rust-lang/rust-clippy
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
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`]
- Loading branch information
Showing
24 changed files
with
1,061 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
use clippy_utils::diagnostics::span_lint_and_help; | ||
use if_chain::if_chain; | ||
use rustc_hir::def::Res; | ||
use rustc_hir::def_id::DefIdSet; | ||
use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath}; | ||
use rustc_lint::LateContext; | ||
|
||
use super::MEM_UNSAFE_FUNCTIONS; | ||
|
||
/// Check extern function definitions. | ||
/// | ||
/// The main purpose of this function is to load `def_ids` of declared external functions. | ||
pub(super) fn check_foreign_item(item: &Item<'_>, blacklist: &[String], blacklist_ids: &mut DefIdSet) { | ||
if let ItemKind::ForeignMod { items, .. } = item.kind { | ||
for f_item in items { | ||
if blacklist.contains(&f_item.ident.as_str().to_string()) { | ||
let f_did = f_item.id.hir_id().owner.def_id.to_def_id(); | ||
blacklist_ids.insert(f_did); | ||
} | ||
} | ||
} | ||
} | ||
|
||
/// Check function call expression | ||
/// | ||
/// Will lint if the name of called function was blacklisted by the configuration. | ||
pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, blacklist_ids: &DefIdSet) { | ||
if_chain! { | ||
if let ExprKind::Call(fn_expr, _) = &expr.kind; | ||
if let ExprKind::Path(qpath) = &fn_expr.kind; | ||
if let QPath::Resolved(_, path) = qpath; | ||
if let Res::Def(_, did) = path.res; | ||
if blacklist_ids.contains(&did); | ||
then { | ||
span_lint_and_help( | ||
cx, | ||
MEM_UNSAFE_FUNCTIONS, | ||
fn_expr.span, | ||
"use of potentially dangerous memory manipulation function", | ||
None, | ||
"consider using its safe version", | ||
); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,159 @@ | ||
mod falliable_memory_allocation; | ||
mod mem_unsafe_functions; | ||
mod passing_string_to_c_functions; | ||
mod untrusted_lib_loading; | ||
|
||
use clippy_utils::def_path_def_ids; | ||
use rustc_hir as hir; | ||
use rustc_hir::def_id::{DefId, DefIdSet}; | ||
use rustc_hir::intravisit; | ||
use rustc_lint::{LateContext, LateLintPass}; | ||
use rustc_session::{declare_tool_lint, impl_lint_pass}; | ||
use rustc_span::def_id::LocalDefId; | ||
use rustc_span::Span; | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// Checks for direct usage of external functions that modify memory | ||
/// without concerning about memory safety, such as `memcpy`, `strcpy`, `strcat` etc. | ||
/// | ||
/// ### Why is this bad? | ||
/// These function can be dangerous when used incorrectly, | ||
/// which could potentially introduce vulnerablities such as buffer overflow to the software. | ||
/// | ||
/// ### Example | ||
/// ```rust | ||
/// extern "C" { | ||
/// fn memcpy(dest: *mut c_void, src: *const c_void, n: size_t) -> *mut c_void; | ||
/// } | ||
/// let ptr = unsafe { memcpy(dest, src, size); } | ||
/// // Or use via libc | ||
/// let ptr = unsafe { libc::memcpy(dest, src, size); } | ||
#[clippy::version = "1.70.0"] | ||
pub MEM_UNSAFE_FUNCTIONS, | ||
nursery, | ||
"use of potentially dangerous external functions" | ||
} | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// | ||
/// ### Why is this bad? | ||
/// | ||
/// ### Example | ||
/// ```rust | ||
/// // example code where clippy issues a warning | ||
/// ``` | ||
/// Use instead: | ||
/// ```rust | ||
/// // example code which does not raise clippy warning | ||
/// ``` | ||
#[clippy::version = "1.70.0"] | ||
pub UNTRUSTED_LIB_LOADING, | ||
nursery, | ||
"attempt to load dynamic library from untrusted source" | ||
} | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// | ||
/// ### Why is this bad? | ||
/// | ||
/// ### Example | ||
/// ```rust | ||
/// // example code where clippy issues a warning | ||
/// ``` | ||
/// Use instead: | ||
/// ```rust | ||
/// // example code which does not raise clippy warning | ||
/// ``` | ||
#[clippy::version = "1.70.0"] | ||
pub PASSING_STRING_TO_C_FUNCTIONS, | ||
nursery, | ||
"passing string or str to extern C function" | ||
} | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// | ||
/// ### Why is this bad? | ||
/// | ||
/// ### Example | ||
/// ```rust | ||
/// // example code where clippy issues a warning | ||
/// ``` | ||
/// Use instead: | ||
/// ```rust | ||
/// // example code which does not raise clippy warning | ||
/// ``` | ||
#[clippy::version = "1.70.0"] | ||
pub FALLIABLE_MEMORY_ALLOCATION, | ||
nursery, | ||
"memory allocation without checking arguments and result" | ||
} | ||
|
||
#[derive(Clone, Default)] | ||
pub struct GuidelineLints { | ||
mem_uns_fns: Vec<String>, | ||
mem_uns_fns_ty_ids: DefIdSet, | ||
} | ||
|
||
impl GuidelineLints { | ||
pub fn new(mem_uns_fns: Vec<String>) -> Self { | ||
Self { | ||
mem_uns_fns, | ||
mem_uns_fns_ty_ids: DefIdSet::new(), | ||
} | ||
} | ||
} | ||
|
||
impl_lint_pass!(GuidelineLints => [ | ||
MEM_UNSAFE_FUNCTIONS, | ||
UNTRUSTED_LIB_LOADING, | ||
PASSING_STRING_TO_C_FUNCTIONS, | ||
FALLIABLE_MEMORY_ALLOCATION, | ||
]); | ||
|
||
impl<'tcx> LateLintPass<'tcx> for GuidelineLints { | ||
fn check_fn( | ||
&mut self, | ||
_cx: &LateContext<'tcx>, | ||
_kind: intravisit::FnKind<'tcx>, | ||
_decl: &'tcx hir::FnDecl<'_>, | ||
_body: &'tcx hir::Body<'_>, | ||
_span: Span, | ||
_def_id: LocalDefId, | ||
) { | ||
} | ||
|
||
fn check_crate(&mut self, cx: &LateContext<'tcx>) { | ||
// Resolve function names to def_ids from configuration | ||
for uns_fns in &self.mem_uns_fns { | ||
// Path like function names such as `libc::foo` or `aa::bb::cc::bar`, | ||
// this only works with dependencies. | ||
if uns_fns.contains("::") { | ||
let path: Vec<&str> = uns_fns.split("::").collect(); | ||
for did in def_path_def_ids(cx, path.as_slice()) { | ||
self.mem_uns_fns_ty_ids.insert(did); | ||
} | ||
} | ||
// Plain function names, then we should take its libc variant into account | ||
else if let Some(did) = libc_fn_def_id(cx, uns_fns) { | ||
self.mem_uns_fns_ty_ids.insert(did); | ||
} | ||
} | ||
} | ||
|
||
fn check_item(&mut self, _cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { | ||
mem_unsafe_functions::check_foreign_item(item, &self.mem_uns_fns, &mut self.mem_uns_fns_ty_ids); | ||
} | ||
|
||
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx hir::Expr<'_>) { | ||
mem_unsafe_functions::check(cx, expr, &self.mem_uns_fns_ty_ids); | ||
} | ||
} | ||
|
||
fn libc_fn_def_id(cx: &LateContext<'_>, fn_name: &str) -> Option<DefId> { | ||
let path = &["libc", fn_name]; | ||
def_path_def_ids(cx, path).next() | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
use clippy_utils::diagnostics::span_lint_and_sugg; | ||
use rustc_ast::ast::{Item, ItemKind}; | ||
use rustc_errors::Applicability; | ||
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; | ||
use rustc_session::{declare_lint_pass, declare_tool_lint}; | ||
|
||
declare_clippy_lint! { | ||
/// ### What it does | ||
/// Checks the external block without explicitly lable its ABI. | ||
/// | ||
/// ### Why is this bad? | ||
/// Implicit ABI has negative impact on code readability. | ||
/// | ||
/// ### Example | ||
/// ```rust | ||
/// extern { | ||
/// fn c_function(); | ||
/// } | ||
/// ``` | ||
/// Use instead: | ||
/// ```rust | ||
/// extern "C" { | ||
/// fn c_function(); | ||
/// } | ||
/// ``` | ||
#[clippy::version = "1.70.0"] | ||
pub IMPLICIT_ABI, | ||
restriction, | ||
"external block with implicit ABI" | ||
} | ||
|
||
declare_lint_pass!(ImplicitAbi => [IMPLICIT_ABI]); | ||
|
||
impl EarlyLintPass for ImplicitAbi { | ||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { | ||
if let ItemKind::ForeignMod(fm) = &item.kind { | ||
if fm.abi.is_none() { | ||
let extern_span = cx.sess().source_map().span_until_whitespace(item.span); | ||
span_lint_and_sugg( | ||
cx, | ||
IMPLICIT_ABI, | ||
extern_span, | ||
"missing ABI label on extern block", | ||
"explicitly states ABI instead", | ||
"extern \"C\"".to_string(), | ||
Applicability::MachineApplicable, | ||
); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.