@@ -37,6 +37,8 @@ pub enum Error {
3737 MmioSize ,
3838 /// Operation would have made the command line too large.
3939 TooLarge ,
40+ /// Double-quotes can be used to protect spaces in values
41+ NoQuoteSpace ,
4042}
4143
4244impl fmt:: Display for Error {
@@ -56,6 +58,10 @@ impl fmt::Display for Error {
5658 "0-sized virtio MMIO device passed to the kernel command line builder."
5759 ) ,
5860 Error :: TooLarge => write ! ( f, "Inserting string would make command line too long." ) ,
61+ Error :: NoQuoteSpace => write ! (
62+ f,
63+ "Value that contains spaces need to be surrounded by quotes"
64+ ) ,
5965 }
6066 }
6167}
@@ -79,7 +85,16 @@ fn valid_str(s: &str) -> Result<()> {
7985 }
8086}
8187
82- fn valid_element ( s : & str ) -> Result < ( ) > {
88+ fn is_quoted ( s : & str ) -> bool {
89+ if let Some ( first_char) = s. chars ( ) . next ( ) {
90+ if let Some ( last_char) = s. chars ( ) . last ( ) {
91+ return first_char == '"' && last_char == '"' ;
92+ }
93+ }
94+ false
95+ }
96+
97+ fn valid_key ( s : & str ) -> Result < ( ) > {
8398 if !s. chars ( ) . all ( valid_char) {
8499 Err ( Error :: InvalidAscii )
85100 } else if s. contains ( ' ' ) {
@@ -91,6 +106,16 @@ fn valid_element(s: &str) -> Result<()> {
91106 }
92107}
93108
109+ fn valid_value ( s : & str ) -> Result < ( ) > {
110+ if !s. chars ( ) . all ( valid_char) {
111+ Err ( Error :: InvalidAscii )
112+ } else if s. contains ( ' ' ) && !is_quoted ( s) {
113+ Err ( Error :: NoQuoteSpace )
114+ } else {
115+ Ok ( ( ) )
116+ }
117+ }
118+
94119/// A builder for a kernel command line string that validates the string as it's being built.
95120///
96121/// # Examples
@@ -155,8 +180,8 @@ impl Cmdline {
155180 let k = key. as_ref ( ) ;
156181 let v = val. as_ref ( ) ;
157182
158- valid_element ( k) ?;
159- valid_element ( v) ?;
183+ valid_key ( k) ?;
184+ valid_value ( v) ?;
160185
161186 let kv_str = format ! ( "{}={}" , k, v) ;
162187
@@ -186,7 +211,7 @@ impl Cmdline {
186211 pub fn insert_multiple < T : AsRef < str > > ( & mut self , key : T , vals : & [ T ] ) -> Result < ( ) > {
187212 let k = key. as_ref ( ) ;
188213
189- valid_element ( k) ?;
214+ valid_key ( k) ?;
190215 if vals. is_empty ( ) {
191216 return Err ( Error :: MissingVal ( k. to_string ( ) ) ) ;
192217 }
@@ -196,7 +221,7 @@ impl Cmdline {
196221 k,
197222 vals. iter( )
198223 . map( |v| -> Result <& str > {
199- valid_element ( v. as_ref( ) ) ?;
224+ valid_value ( v. as_ref( ) ) ?;
200225 Ok ( v. as_ref( ) )
201226 } )
202227 . collect:: <Result <Vec <& str >>>( ) ?
@@ -565,20 +590,24 @@ mod tests {
565590 fn test_insert_space ( ) {
566591 let mut cl = Cmdline :: new ( 100 ) . unwrap ( ) ;
567592 assert_eq ! ( cl. insert( "a " , "b" ) , Err ( Error :: HasSpace ) ) ;
568- assert_eq ! ( cl. insert( "a" , "b " ) , Err ( Error :: HasSpace ) ) ;
593+ assert_eq ! ( cl. insert( "a" , "b " ) , Err ( Error :: NoQuoteSpace ) ) ;
569594 assert_eq ! ( cl. insert( "a " , "b " ) , Err ( Error :: HasSpace ) ) ;
570595 assert_eq ! ( cl. insert( " a" , "b" ) , Err ( Error :: HasSpace ) ) ;
571596 assert_eq ! ( cl. as_cstring( ) . unwrap( ) . as_bytes_with_nul( ) , b"\0 " ) ;
597+ assert ! ( cl. insert( "a" , "\" b b\" " ) . is_ok( ) ) ;
598+ assert ! ( cl. insert( "c" , "\" d\" " ) . is_ok( ) ) ;
599+ assert_eq ! (
600+ cl. as_cstring( ) . unwrap( ) . as_bytes_with_nul( ) ,
601+ b"a=\" b b\" c=\" d\" \0 "
602+ ) ;
572603 }
573604
574605 #[ test]
575606 fn test_insert_equals ( ) {
576607 let mut cl = Cmdline :: new ( 100 ) . unwrap ( ) ;
577608 assert_eq ! ( cl. insert( "a=" , "b" ) , Err ( Error :: HasEquals ) ) ;
578- assert_eq ! ( cl. insert( "a" , "b=" ) , Err ( Error :: HasEquals ) ) ;
579609 assert_eq ! ( cl. insert( "a=" , "b " ) , Err ( Error :: HasEquals ) ) ;
580610 assert_eq ! ( cl. insert( "=a" , "b" ) , Err ( Error :: HasEquals ) ) ;
581- assert_eq ! ( cl. insert( "a" , "=b" ) , Err ( Error :: HasEquals ) ) ;
582611 assert_eq ! ( cl. as_cstring( ) . unwrap( ) . as_bytes_with_nul( ) , b"\0 " ) ;
583612 }
584613
@@ -700,7 +729,10 @@ mod tests {
700729 cl. insert_multiple( "foo" , & no_vals) ,
701730 Err ( Error :: MissingVal ( "foo" . to_string( ) ) )
702731 ) ;
703- assert_eq ! ( cl. insert_multiple( "foo" , & [ "bar " ] ) , Err ( Error :: HasSpace ) ) ;
732+ assert_eq ! (
733+ cl. insert_multiple( "foo" , & [ "bar " ] ) ,
734+ Err ( Error :: NoQuoteSpace )
735+ ) ;
704736 assert_eq ! (
705737 cl. insert_multiple( "foo" , & [ "bar" , "baz" ] ) ,
706738 Err ( Error :: TooLarge )
0 commit comments