]> git.proxmox.com Git - rustc.git/blame - src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
New upstream version 1.75.0+dfsg1
[rustc.git] / src / tools / clippy / clippy_lints / src / non_octal_unix_permissions.rs
CommitLineData
cdc7bbd5
XL
1use clippy_utils::diagnostics::span_lint_and_sugg;
2use clippy_utils::source::{snippet_opt, snippet_with_applicability};
cdc7bbd5
XL
3use clippy_utils::{match_def_path, paths};
4use if_chain::if_chain;
5use rustc_errors::Applicability;
6use rustc_hir::{Expr, ExprKind};
7use rustc_lint::{LateContext, LateLintPass};
8use rustc_session::{declare_lint_pass, declare_tool_lint};
2b03887a 9use rustc_span::sym;
cdc7bbd5
XL
10
11declare_clippy_lint! {
94222f64
XL
12 /// ### What it does
13 /// Checks for non-octal values used to set Unix file permissions.
cdc7bbd5 14 ///
94222f64
XL
15 /// ### Why is this bad?
16 /// They will be converted into octal, creating potentially
cdc7bbd5
XL
17 /// unintended file permissions.
18 ///
94222f64 19 /// ### Example
cdc7bbd5
XL
20 /// ```rust,ignore
21 /// use std::fs::OpenOptions;
22 /// use std::os::unix::fs::OpenOptionsExt;
23 ///
24 /// let mut options = OpenOptions::new();
25 /// options.mode(644);
26 /// ```
27 /// Use instead:
28 /// ```rust,ignore
29 /// use std::fs::OpenOptions;
30 /// use std::os::unix::fs::OpenOptionsExt;
31 ///
32 /// let mut options = OpenOptions::new();
33 /// options.mode(0o644);
34 /// ```
a2a8927a 35 #[clippy::version = "1.53.0"]
cdc7bbd5
XL
36 pub NON_OCTAL_UNIX_PERMISSIONS,
37 correctness,
38 "use of non-octal value to set unix file permissions, which will be translated into octal"
39}
40
41declare_lint_pass!(NonOctalUnixPermissions => [NON_OCTAL_UNIX_PERMISSIONS]);
42
5099ac24 43impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
cdc7bbd5
XL
44 fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
45 match &expr.kind {
f2b60f7d 46 ExprKind::MethodCall(path, func, [param], _) => {
cdc7bbd5 47 if_chain! {
ed00b5ec 48 if let Some(adt) = cx.typeck_results().expr_ty(func).peel_refs().ty_adt_def();
cdc7bbd5 49 if (path.ident.name == sym!(mode)
ed00b5ec
FG
50 && matches!(cx.tcx.get_diagnostic_name(adt.did()), Some(sym::FsOpenOptions | sym::DirBuilder)))
51 || (path.ident.name == sym!(set_mode)
52 && cx.tcx.is_diagnostic_item(sym::FsPermissions, adt.did()));
cdc7bbd5 53 if let ExprKind::Lit(_) = param.kind;
ed00b5ec 54 if param.span.eq_ctxt(expr.span);
cdc7bbd5
XL
55
56 then {
2b03887a
FG
57 let Some(snip) = snippet_opt(cx, param.span) else {
58 return
cdc7bbd5
XL
59 };
60
61 if !snip.starts_with("0o") {
62 show_error(cx, param);
63 }
64 }
65 }
66 },
67 ExprKind::Call(func, [param]) => {
68 if_chain! {
69 if let ExprKind::Path(ref path) = func.kind;
70 if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
71 if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE);
72 if let ExprKind::Lit(_) = param.kind;
ed00b5ec 73 if param.span.eq_ctxt(expr.span);
2b03887a
FG
74 if let Some(snip) = snippet_opt(cx, param.span);
75 if !snip.starts_with("0o");
cdc7bbd5 76 then {
2b03887a 77 show_error(cx, param);
cdc7bbd5
XL
78 }
79 }
80 },
81 _ => {},
82 };
83 }
84}
85
86fn show_error(cx: &LateContext<'_>, param: &Expr<'_>) {
87 let mut applicability = Applicability::MachineApplicable;
88 span_lint_and_sugg(
89 cx,
90 NON_OCTAL_UNIX_PERMISSIONS,
91 param.span,
92 "using a non-octal value to set unix file permissions",
93 "consider using an octal literal instead",
94 format!(
95 "0o{}",
96 snippet_with_applicability(cx, param.span, "0o..", &mut applicability,),
97 ),
98 applicability,
99 );
100}