]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_lints/src/non_octal_unix_permissions.rs
Auto merge of #103217 - mejrs:track, r=eholk
[rust.git] / src / tools / clippy / clippy_lints / src / non_octal_unix_permissions.rs
1 use clippy_utils::diagnostics::span_lint_and_sugg;
2 use clippy_utils::source::{snippet_opt, snippet_with_applicability};
3 use clippy_utils::ty::{is_type_diagnostic_item, match_type};
4 use clippy_utils::{match_def_path, paths};
5 use if_chain::if_chain;
6 use rustc_errors::Applicability;
7 use rustc_hir::{Expr, ExprKind};
8 use rustc_lint::{LateContext, LateLintPass};
9 use rustc_session::{declare_lint_pass, declare_tool_lint};
10 use rustc_span::sym;
11
12 declare_clippy_lint! {
13     /// ### What it does
14     /// Checks for non-octal values used to set Unix file permissions.
15     ///
16     /// ### Why is this bad?
17     /// They will be converted into octal, creating potentially
18     /// unintended file permissions.
19     ///
20     /// ### Example
21     /// ```rust,ignore
22     /// use std::fs::OpenOptions;
23     /// use std::os::unix::fs::OpenOptionsExt;
24     ///
25     /// let mut options = OpenOptions::new();
26     /// options.mode(644);
27     /// ```
28     /// Use instead:
29     /// ```rust,ignore
30     /// use std::fs::OpenOptions;
31     /// use std::os::unix::fs::OpenOptionsExt;
32     ///
33     /// let mut options = OpenOptions::new();
34     /// options.mode(0o644);
35     /// ```
36     #[clippy::version = "1.53.0"]
37     pub NON_OCTAL_UNIX_PERMISSIONS,
38     correctness,
39     "use of non-octal value to set unix file permissions, which will be translated into octal"
40 }
41
42 declare_lint_pass!(NonOctalUnixPermissions => [NON_OCTAL_UNIX_PERMISSIONS]);
43
44 impl<'tcx> LateLintPass<'tcx> for NonOctalUnixPermissions {
45     fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) {
46         match &expr.kind {
47             ExprKind::MethodCall(path, func, [param], _) => {
48                 let obj_ty = cx.typeck_results().expr_ty(func).peel_refs();
49
50                 if_chain! {
51                     if (path.ident.name == sym!(mode)
52                         && (match_type(cx, obj_ty, &paths::OPEN_OPTIONS)
53                             || is_type_diagnostic_item(cx, obj_ty, sym::DirBuilder)))
54                         || (path.ident.name == sym!(set_mode) && match_type(cx, obj_ty, &paths::PERMISSIONS));
55                     if let ExprKind::Lit(_) = param.kind;
56
57                     then {
58                         let Some(snip) = snippet_opt(cx, param.span) else {
59                             return
60                         };
61
62                         if !snip.starts_with("0o") {
63                             show_error(cx, param);
64                         }
65                     }
66                 }
67             },
68             ExprKind::Call(func, [param]) => {
69                 if_chain! {
70                     if let ExprKind::Path(ref path) = func.kind;
71                     if let Some(def_id) = cx.qpath_res(path, func.hir_id).opt_def_id();
72                     if match_def_path(cx, def_id, &paths::PERMISSIONS_FROM_MODE);
73                     if let ExprKind::Lit(_) = param.kind;
74                     if let Some(snip) = snippet_opt(cx, param.span);
75                     if !snip.starts_with("0o");
76                     then {
77                         show_error(cx, param);
78                     }
79                 }
80             },
81             _ => {},
82         };
83     }
84 }
85
86 fn 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 }