@@ -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;
@@ -3563,6 +3564,43 @@ declare_clippy_lint! {
3563
3564
"calls to `.take()` or `.skip()` that are out of bounds"
3564
3565
}
3565
3566
3567
+ declare_clippy_lint ! {
3568
+ /// ### What it does
3569
+ /// Checks for calls to `Path::join` that start with a path separator, like `\\` or `/`..
3570
+ ///
3571
+ /// ### Why is this bad?
3572
+ /// `.join()` arguments starting with a separator (`/` or `\\`) can replace the entire path.
3573
+ /// If this is intentional, prefer using `Path::new()` instead.
3574
+ ///
3575
+ /// See [`Path::join()`](https://doc.rust-lang.org/std/path/struct.Path.html#method.join)
3576
+ ///
3577
+ /// ### Example
3578
+ /// ```rust
3579
+ /// # use std::path::{Path, PathBuf};
3580
+ /// let path = Path::new("/bin");
3581
+ /// let joined_path = path.join("/sh");
3582
+ /// assert_eq!(joined_path, PathBuf::from("/sh"));
3583
+ /// ```
3584
+ ///
3585
+ /// Use instead;
3586
+ /// ```rust
3587
+ /// # use std::path::{Path, PathBuf};
3588
+ /// let path = Path::new("/bin");
3589
+ ///
3590
+ /// // If this was unintentional, remove the leading separator
3591
+ /// let joined_path = path.join("sh");
3592
+ /// assert_eq!(joined_path, PathBuf::from("/bin/sh"));
3593
+ ///
3594
+ /// // If this was intentional, create a new path instead
3595
+ /// let new = Path::new("/sh");
3596
+ /// assert_eq!(new, PathBuf::from("/sh"));
3597
+ /// ```
3598
+ #[ clippy:: version = "1.74.0" ]
3599
+ pub JOIN_ABSOLUTE_PATHS ,
3600
+ correctness,
3601
+ "arg to .join called on a `Path` contains leading separator"
3602
+ }
3603
+
3566
3604
pub struct Methods {
3567
3605
avoid_breaking_exported_api : bool ,
3568
3606
msrv : Msrv ,
@@ -3703,6 +3741,7 @@ impl_lint_pass!(Methods => [
3703
3741
FILTER_MAP_BOOL_THEN ,
3704
3742
READONLY_WRITE_LOCK ,
3705
3743
ITER_OUT_OF_BOUNDS ,
3744
+ JOIN_ABSOLUTE_PATHS ,
3706
3745
] ) ;
3707
3746
3708
3747
/// Extracts a method call name, args, and `Span` of the method name.
@@ -4062,6 +4101,8 @@ impl Methods {
4062
4101
( "join" , [ join_arg] ) => {
4063
4102
if let Some ( ( "collect" , _, _, span, _) ) = method_call ( recv) {
4064
4103
unnecessary_join:: check ( cx, expr, recv, join_arg, span) ;
4104
+ } else {
4105
+ join_absolute_paths:: check ( cx, recv, join_arg) ;
4065
4106
}
4066
4107
} ,
4067
4108
( "last" , [ ] ) => {
0 commit comments