@@ -8,12 +8,21 @@ pub struct PathQuotedDisplay<'a> {
88 path : & ' a Path ,
99}
1010
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+
1122impl < ' a > Display for PathQuotedDisplay < ' a > {
1223 fn fmt ( & self , f : & mut std:: fmt:: Formatter < ' _ > ) -> std:: fmt:: Result {
1324 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) {
1726 return f. write_str ( s) ;
1827 }
1928 }
@@ -45,11 +54,30 @@ mod tests {
4554
4655 #[ test]
4756 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+ ] {
4968 assert_eq ! ( v, format!( "{}" , PathQuotedDisplay :: new( & v) ) ) ;
5069 }
5170 }
5271
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+
5381 #[ test]
5482 fn test_quoted ( ) {
5583 let cases = [
@@ -59,7 +87,12 @@ mod tests {
5987 ( r#"/path/"withquotes'"# , r#""/path/\"withquotes'""# ) ,
6088 ] ;
6189 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 ] ) ;
6396 }
6497 }
6598
0 commit comments