@@ -85,16 +85,47 @@ impl FromStr for MapsEntry {
85
85
// e.g.: "ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]"
86
86
// e.g.: "7f5985f46000-7f5985f48000 rw-p 00039000 103:06 76021795 /usr/lib/x86_64-linux-gnu/ld-linux-x86-64.so.2"
87
87
// 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).
88
91
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 ( ) ;
98
129
99
130
let hex = |s| usize:: from_str_radix ( s, 16 ) . map_err ( |_| "Couldn't parse hex number" ) ;
100
131
let address = if let Some ( ( start, limit) ) = range_str. split_once ( '-' ) {
@@ -229,4 +260,18 @@ fn check_maps_entry_parsing_32bit() {
229
260
pathname: Default :: default ( ) ,
230
261
}
231
262
) ;
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
+ ) ;
232
277
}
0 commit comments