1 use clippy_utils::diagnostics::span_lint_and_then; 2 use clippy_utils::paths; 3 use clippy_utils::ty::match_type; 4 use rustc_ast::ast::LitKind; 5 use rustc_hir::{Expr, ExprKind}; 6 use rustc_lint::{LateContext, LateLintPass}; 7 use rustc_session::{declare_lint_pass, declare_tool_lint}; 8 9 declare_clippy_lint! { 10 /// ### What it does 11 /// Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`. 12 /// 13 /// ### Why is this bad? 14 /// On Unix platforms this results in the file being world writable, 15 /// equivalent to `chmod a+w <file>`. 16 /// ### Example 17 /// ```rust 18 /// use std::fs::File; 19 /// let f = File::create("foo.txt").unwrap(); 20 /// let metadata = f.metadata().unwrap(); 21 /// let mut permissions = metadata.permissions(); 22 /// permissions.set_readonly(false); 23 /// ``` 24 #[clippy::version = "1.68.0"] 25 pub PERMISSIONS_SET_READONLY_FALSE, 26 suspicious, 27 "Checks for calls to `std::fs::Permissions.set_readonly` with argument `false`" 28 } 29 declare_lint_pass!(PermissionsSetReadonlyFalse => [PERMISSIONS_SET_READONLY_FALSE]); 30 31 impl<'tcx> LateLintPass<'tcx> for PermissionsSetReadonlyFalse { check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>)32 fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { 33 if let ExprKind::MethodCall(path, receiver, [arg], _) = &expr.kind 34 && match_type(cx, cx.typeck_results().expr_ty(receiver), &paths::PERMISSIONS) 35 && path.ident.name == sym!(set_readonly) 36 && let ExprKind::Lit(lit) = &arg.kind 37 && LitKind::Bool(false) == lit.node 38 { 39 span_lint_and_then( 40 cx, 41 PERMISSIONS_SET_READONLY_FALSE, 42 expr.span, 43 "call to `set_readonly` with argument `false`", 44 |diag| { 45 diag.note("on Unix platforms this results in the file being world writable"); 46 diag.help("you can set the desired permissions using `PermissionsExt`. For more information, see\n\ 47 https://doc.rust-lang.org/std/os/unix/fs/trait.PermissionsExt.html"); 48 } 49 ); 50 } 51 } 52 } 53