@@ -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;
@@ -3682,6 +3683,42 @@ declare_clippy_lint! {
3682
3683
"calling the `try_from` and `try_into` trait methods when `From`/`Into` is implemented"
3683
3684
}
3684
3685
3686
+ declare_clippy_lint ! {
3687
+ /// Checks for calls to `Path::join` that start with a path separator, like `\\` or `/`..
3688
+ ///
3689
+ /// ### Why is this bad?
3690
+ /// `.join()` arguments starting with a separator (`/` or `\\`) can replace the entire path.
3691
+ /// If this is intentional, prefer using `Path::new()` instead.
3692
+ ///
3693
+ /// See [`Path::join()`](https://doc.rust-lang.org/std/path/struct.Path.html#method.join)
3694
+ ///
3695
+ /// ### Example
3696
+ /// ```rust
3697
+ /// # use std::path::{Path, PathBuf};
3698
+ /// let path = Path::new("/bin");
3699
+ /// let joined_path = path.join("/sh");
3700
+ /// assert_eq!(joined_path, PathBuf::from("/sh"));
3701
+ /// ```
3702
+ ///
3703
+ /// Use instead;
3704
+ /// ```rust
3705
+ /// # use std::path::{Path, PathBuf};
3706
+ /// let path = Path::new("/bin");
3707
+ ///
3708
+ /// // If this was unintentional, remove the leading separator
3709
+ /// let joined_path = path.join("sh");
3710
+ /// assert_eq!(joined_path, PathBuf::from("/bin/sh"));
3711
+ ///
3712
+ /// // If this was intentional, create a new path instead
3713
+ /// let new = Path::new("/sh");
3714
+ /// assert_eq!(new, PathBuf::from("/sh"));
3715
+ /// ```
3716
+ #[ clippy:: version = "1.75.0" ]
3717
+ pub JOIN_ABSOLUTE_PATHS ,
3718
+ correctness,
3719
+ "arg to .join called on a `Path` contains leading separator"
3720
+ }
3721
+
3685
3722
pub struct Methods {
3686
3723
avoid_breaking_exported_api : bool ,
3687
3724
msrv : Msrv ,
@@ -3829,6 +3866,7 @@ impl_lint_pass!(Methods => [
3829
3866
REDUNDANT_AS_STR ,
3830
3867
WAKER_CLONE_WAKE ,
3831
3868
UNNECESSARY_FALLIBLE_CONVERSIONS ,
3869
+ JOIN_ABSOLUTE_PATHS ,
3832
3870
] ) ;
3833
3871
3834
3872
/// Extracts a method call name, args, and `Span` of the method name.
@@ -4231,6 +4269,8 @@ impl Methods {
4231
4269
( "join" , [ join_arg] ) => {
4232
4270
if let Some ( ( "collect" , _, _, span, _) ) = method_call ( recv) {
4233
4271
unnecessary_join:: check ( cx, expr, recv, join_arg, span) ;
4272
+ } else {
4273
+ join_absolute_paths:: check ( cx, recv, join_arg) ;
4234
4274
}
4235
4275
} ,
4236
4276
( "last" , [ ] ) => {
0 commit comments