@@ -85,16 +85,47 @@ impl FromStr for MapsEntry {
8585 // e.g.: "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]"
8686 // e.g.: "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
8787 // e.g.: "35b1a21000-35b1a22000 rw-p 00000000 00:00 0"
88+ //
89+ // Note that paths may contain spaces, so we can't use `str::split` for parsing (until
90+ // Split::remainder is stabalized #77998).
8891 fn from_str ( s : & str ) -> Result < Self , Self :: Err > {
89- let mut parts = s
90- . split ( ' ' ) // space-separated fields
91- . filter ( |s| s. len ( ) > 0 ) ; // multiple spaces implies empty strings that need to be skipped.
92- let range_str = parts. next ( ) . ok_or ( "Couldn't find address" ) ?;
93- let perms_str = parts. next ( ) . ok_or ( "Couldn't find permissions" ) ?;
94- let offset_str = parts. next ( ) . ok_or ( "Couldn't find offset" ) ?;
95- let dev_str = parts. next ( ) . ok_or ( "Couldn't find dev" ) ?;
96- let inode_str = parts. next ( ) . ok_or ( "Couldn't find inode" ) ?;
97- let pathname_str = parts. next ( ) . unwrap_or ( "" ) ; // pathname may be omitted.
92+ let ( range_str, s) = s. trim ( )
93+ . split_once ( ' ' )
94+ . unwrap_or ( ( s, "" ) ) ;
95+ if range_str. is_empty ( ) {
96+ return Err ( "Couldn't find address" ) ;
97+ }
98+
99+ let ( perms_str, s) = s. trim ( )
100+ . split_once ( ' ' )
101+ . unwrap_or ( ( s, "" ) ) ;
102+ if range_str. is_empty ( ) {
103+ return Err ( "Couldn't find permissions" ) ;
104+ }
105+
106+ let ( offset_str, s) = s. trim ( )
107+ . split_once ( ' ' )
108+ . unwrap_or ( ( s, "" ) ) ;
109+ if range_str. is_empty ( ) {
110+ return Err ( "Couldn't find offset" ) ;
111+ }
112+
113+ let ( dev_str, s) = s. trim ( )
114+ . split_once ( ' ' )
115+ . unwrap_or ( ( s, "" ) ) ;
116+ if range_str. is_empty ( ) {
117+ return Err ( "Couldn't find dev" ) ;
118+ }
119+
120+ let ( inode_str, s) = s. trim ( )
121+ . split_once ( ' ' )
122+ . unwrap_or ( ( s, "" ) ) ;
123+ if range_str. is_empty ( ) {
124+ return Err ( "Couldn't find inode" ) ;
125+ }
126+
127+ // Pathname may be omitted in which case it will be empty
128+ let pathname_str = s. trim ( ) ;
98129
99130 let hex = |s| usize:: from_str_radix ( s, 16 ) . map_err ( |_| "Couldn't parse hex number" ) ;
100131 let address = if let Some ( ( start, limit) ) = range_str. split_once ( '-' ) {
@@ -229,4 +260,18 @@ fn check_maps_entry_parsing_32bit() {
229260 pathname: Default :: default ( ) ,
230261 }
231262 ) ;
263+ assert_eq ! (
264+ "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
265+ /executable/path/with some spaces"
266+ . parse:: <MapsEntry >( )
267+ . unwrap( ) ,
268+ MapsEntry {
269+ address: ( 0xb7c79000 , 0xb7e02000 ) ,
270+ perms: [ 'r' , '-' , '-' , 'p' ] ,
271+ offset: 0x00000000 ,
272+ dev: ( 0x08 , 0x01 ) ,
273+ inode: 0x60662705 ,
274+ pathname: "/executable/path/with some spaces" . into( ) ,
275+ }
276+ ) ;
232277}
0 commit comments