@@ -8,12 +8,21 @@ pub struct PathQuotedDisplay<'a> {
8
8
path : & ' a Path ,
9
9
}
10
10
11
+ /// A pretty conservative check for "shell safe" characters. These
12
+ /// are basically ones which are very common in filenames or command line
13
+ /// arguments, which are the primary use case for this. There are definitely
14
+ /// characters such as '+' which are typically safe, but it's fine if
15
+ /// we're overly conservative.
16
+ ///
17
+ /// For bash for example: https://www.gnu.org/software/bash/manual/html_node/Definitions.html#index-metacharacter
18
+ fn is_shellsafe ( c : char ) -> bool {
19
+ matches ! ( c, '/' | '.' | '-' | '_' | ',' | '=' | ':' ) || c. is_alphanumeric ( )
20
+ }
21
+
11
22
impl < ' a > Display for PathQuotedDisplay < ' a > {
12
23
fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
13
24
if let Some ( s) = self . path . to_str ( ) {
14
- if s. chars ( )
15
- . all ( |c| matches ! ( c, '/' | '.' ) || c. is_alphanumeric ( ) )
16
- {
25
+ if s. chars ( ) . all ( is_shellsafe) {
17
26
return f. write_str ( s) ;
18
27
}
19
28
}
@@ -45,11 +54,30 @@ mod tests {
45
54
46
55
#[ test]
47
56
fn test_unquoted ( ) {
48
- for v in [ "" , "foo" , "/foo/bar" , "/foo/bar/../baz" , "/foo9/bar10" ] {
57
+ for v in [
58
+ "" ,
59
+ "foo" ,
60
+ "/foo/bar" ,
61
+ "/foo/bar/../baz" ,
62
+ "/foo9/bar10" ,
63
+ "--foo" ,
64
+ "--virtiofs=/foo,/bar" ,
65
+ "/foo:/bar" ,
66
+ "--label=type=unconfined_t" ,
67
+ ] {
49
68
assert_eq ! ( v, format!( "{}" , PathQuotedDisplay :: new( & v) ) ) ;
50
69
}
51
70
}
52
71
72
+ #[ test]
73
+ fn test_bash_metachars ( ) {
74
+ // https://www.gnu.org/software/bash/manual/html_node/Definitions.html#index-metacharacter
75
+ let bash_metachars = "|&;()<>" ;
76
+ for c in bash_metachars. chars ( ) {
77
+ assert ! ( !is_shellsafe( c) ) ;
78
+ }
79
+ }
80
+
53
81
#[ test]
54
82
fn test_quoted ( ) {
55
83
let cases = [
@@ -59,7 +87,12 @@ mod tests {
59
87
( r#"/path/"withquotes'"# , r#""/path/\"withquotes'""# ) ,
60
88
] ;
61
89
for ( v, quoted) in cases {
62
- assert_eq ! ( quoted, format!( "{}" , PathQuotedDisplay :: new( & v) ) ) ;
90
+ let q = PathQuotedDisplay :: new ( & v) . to_string ( ) ;
91
+ assert_eq ! ( quoted, q. as_str( ) ) ;
92
+ // Also sanity check there's exactly one token
93
+ let token = shlex:: split ( & q) . unwrap ( ) ;
94
+ assert_eq ! ( 1 , token. len( ) ) ;
95
+ assert_eq ! ( v, token[ 0 ] ) ;
63
96
}
64
97
}
65
98
0 commit comments