Skip to content

Commit 0e3dcd1

Browse files
mcartonManishearth
authored andcommitted
Improve NOT_UNSAFE_PTR_ARG_DEREF with functions
1 parent 7781f1d commit 0e3dcd1

File tree

3 files changed

+40
-21
lines changed

3 files changed

+40
-21
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ Table of contents:
1717

1818
## Lints
1919

20-
There are 157 lints included in this crate:
20+
There are 158 lints included in this crate:
2121

2222
name | default | meaning
2323
---------------------------------------------------------------------------------------------------------------------|---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

clippy_lints/src/functions.rs

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -88,15 +88,15 @@ impl LateLintPass for Functions {
8888
self.check_arg_number(cx, decl, span);
8989
}
9090

91-
self.check_raw_ptr(cx, unsafety, decl, block, span, nodeid);
91+
self.check_raw_ptr(cx, unsafety, decl, block, nodeid);
9292
}
9393

9494
fn check_trait_item(&mut self, cx: &LateContext, item: &hir::TraitItem) {
9595
if let hir::MethodTraitItem(ref sig, ref block) = item.node {
9696
self.check_arg_number(cx, &sig.decl, item.span);
9797

9898
if let Some(ref block) = *block {
99-
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, block, item.span, item.id);
99+
self.check_raw_ptr(cx, sig.unsafety, &sig.decl, block, item.id);
100100
}
101101
}
102102
}
@@ -113,7 +113,7 @@ impl Functions {
113113
}
114114
}
115115

116-
fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, block: &hir::Block, span: Span, nodeid: ast::NodeId) {
116+
fn check_raw_ptr(&self, cx: &LateContext, unsafety: hir::Unsafety, decl: &hir::FnDecl, block: &hir::Block, nodeid: ast::NodeId) {
117117
if unsafety == hir::Unsafety::Normal && cx.access_levels.is_exported(nodeid) {
118118
let raw_ptrs = decl.inputs.iter().filter_map(|arg| raw_ptr_arg(cx, arg)).collect::<HashSet<_>>();
119119

@@ -144,32 +144,43 @@ struct DerefVisitor<'a, 'tcx: 'a> {
144144

145145
impl<'a, 'tcx, 'v> hir::intravisit::Visitor<'v> for DerefVisitor<'a, 'tcx> {
146146
fn visit_expr(&mut self, expr: &'v hir::Expr) {
147-
let ptr = match expr.node {
148-
hir::ExprUnary(hir::UnDeref, ref ptr) => Some(ptr),
147+
match expr.node {
148+
hir::ExprCall(ref f, ref args) => {
149+
let ty = self.cx.tcx.expr_ty(f);
150+
151+
if type_is_unsafe_function(ty) {
152+
for arg in args {
153+
self.check_arg(arg);
154+
}
155+
}
156+
}
149157
hir::ExprMethodCall(_, _, ref args) => {
150158
let method_call = ty::MethodCall::expr(expr.id);
151159
let base_type = self.cx.tcx.tables.borrow().method_map[&method_call].ty;
152160

153161
if type_is_unsafe_function(base_type) {
154-
Some(&args[0])
155-
} else {
156-
None
157-
}
158-
}
159-
_ => None,
160-
};
161-
162-
if let Some(ptr) = ptr {
163-
if let Some(def) = self.cx.tcx.def_map.borrow().get(&ptr.id) {
164-
if self.ptrs.contains(&def.def_id()) {
165-
span_lint(self.cx,
166-
NOT_UNSAFE_PTR_ARG_DEREF,
167-
ptr.span,
168-
"this public function dereferences a raw pointer but is not marked `unsafe`");
162+
for arg in args {
163+
self.check_arg(arg);
164+
}
169165
}
170166
}
167+
hir::ExprUnary(hir::UnDeref, ref ptr) => self.check_arg(ptr),
168+
_ => (),
171169
}
172170

173171
hir::intravisit::walk_expr(self, expr);
174172
}
175173
}
174+
175+
impl<'a, 'tcx: 'a> DerefVisitor<'a, 'tcx> {
176+
fn check_arg(&self, ptr: &hir::Expr) {
177+
if let Some(def) = self.cx.tcx.def_map.borrow().get(&ptr.id) {
178+
if self.ptrs.contains(&def.def_id()) {
179+
span_lint(self.cx,
180+
NOT_UNSAFE_PTR_ARG_DEREF,
181+
ptr.span,
182+
"this public function dereferences a raw pointer but is not marked `unsafe`");
183+
}
184+
}
185+
}
186+
}

tests/compile-fail/functions.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ impl Foo for Bar {
3636
fn ptr(p: *const u8) {
3737
println!("{}", unsafe { *p });
3838
//~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe`
39+
println!("{:?}", unsafe { p.as_ref() });
40+
//~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe`
41+
unsafe { std::ptr::read(p) };
42+
//~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe`
3943
}
4044
}
4145

@@ -50,6 +54,8 @@ pub fn public(p: *const u8) {
5054
//~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe`
5155
println!("{:?}", unsafe { p.as_ref() });
5256
//~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe`
57+
unsafe { std::ptr::read(p) };
58+
//~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe`
5359
}
5460

5561
impl Bar {
@@ -62,6 +68,8 @@ impl Bar {
6268
//~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe`
6369
println!("{:?}", unsafe { p.as_ref() });
6470
//~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe`
71+
unsafe { std::ptr::read(p) };
72+
//~^ ERROR: this public function dereferences a raw pointer but is not marked `unsafe`
6573
}
6674

6775
pub fn public_ok(self, p: *const u8) {

0 commit comments

Comments
 (0)