@@ -49,6 +49,7 @@ mod iter_skip_next;
49
49
mod iter_skip_zero;
50
50
mod iter_with_drain;
51
51
mod iterator_step_by_zero;
52
+ mod join_absolute_paths;
52
53
mod manual_next_back;
53
54
mod manual_ok_or;
54
55
mod manual_saturating_arithmetic;
@@ -3631,6 +3632,42 @@ declare_clippy_lint! {
3631
3632
"`as_str` used to call a method on `str` that is also available on `String`"
3632
3633
}
3633
3634
3635
+ declare_clippy_lint ! {
3636
+ /// Checks for calls to `Path::join` that start with a path separator, like `\\` or `/`..
3637
+ ///
3638
+ /// ### Why is this bad?
3639
+ /// `.join()` arguments starting with a separator (`/` or `\\`) can replace the entire path.
3640
+ /// If this is intentional, prefer using `Path::new()` instead.
3641
+ ///
3642
+ /// See [`Path::join()`](https://doc.rust-lang.org/std/path/struct.Path.html#method.join)
3643
+ ///
3644
+ /// ### Example
3645
+ /// ```rust
3646
+ /// # use std::path::{Path, PathBuf};
3647
+ /// let path = Path::new("/bin");
3648
+ /// let joined_path = path.join("/sh");
3649
+ /// assert_eq!(joined_path, PathBuf::from("/sh"));
3650
+ /// ```
3651
+ ///
3652
+ /// Use instead;
3653
+ /// ```rust
3654
+ /// # use std::path::{Path, PathBuf};
3655
+ /// let path = Path::new("/bin");
3656
+ ///
3657
+ /// // If this was unintentional, remove the leading separator
3658
+ /// let joined_path = path.join("sh");
3659
+ /// assert_eq!(joined_path, PathBuf::from("/bin/sh"));
3660
+ ///
3661
+ /// // If this was intentional, create a new path instead
3662
+ /// let new = Path::new("/sh");
3663
+ /// assert_eq!(new, PathBuf::from("/sh"));
3664
+ /// ```
3665
+ #[ clippy:: version = "1.74.0" ]
3666
+ pub JOIN_ABSOLUTE_PATHS ,
3667
+ correctness,
3668
+ "arg to .join called on a `Path` contains leading separator"
3669
+ }
3670
+
3634
3671
pub struct Methods {
3635
3672
avoid_breaking_exported_api : bool ,
3636
3673
msrv : Msrv ,
@@ -3776,6 +3813,7 @@ impl_lint_pass!(Methods => [
3776
3813
ITER_OUT_OF_BOUNDS ,
3777
3814
PATH_ENDS_WITH_EXT ,
3778
3815
REDUNDANT_AS_STR ,
3816
+ JOIN_ABSOLUTE_PATHS ,
3779
3817
] ) ;
3780
3818
3781
3819
/// Extracts a method call name, args, and `Span` of the method name.
@@ -4139,6 +4177,8 @@ impl Methods {
4139
4177
( "join" , [ join_arg] ) => {
4140
4178
if let Some ( ( "collect" , _, _, span, _) ) = method_call ( recv) {
4141
4179
unnecessary_join:: check ( cx, expr, recv, join_arg, span) ;
4180
+ } else {
4181
+ join_absolute_paths:: check ( cx, recv, join_arg) ;
4142
4182
}
4143
4183
} ,
4144
4184
( "last" , [ ] ) => {
0 commit comments