@@ -85,16 +85,37 @@ 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 stabilized #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_start ( ) . split_once ( ' ' ) . unwrap_or ( ( s, "" ) ) ;
93
+ if range_str. is_empty ( ) {
94
+ return Err ( "Couldn't find address" ) ;
95
+ }
96
+
97
+ let ( perms_str, s) = s. trim_start ( ) . split_once ( ' ' ) . unwrap_or ( ( s, "" ) ) ;
98
+ if perms_str. is_empty ( ) {
99
+ return Err ( "Couldn't find permissions" ) ;
100
+ }
101
+
102
+ let ( offset_str, s) = s. trim_start ( ) . split_once ( ' ' ) . unwrap_or ( ( s, "" ) ) ;
103
+ if offset_str. is_empty ( ) {
104
+ return Err ( "Couldn't find offset" ) ;
105
+ }
106
+
107
+ let ( dev_str, s) = s. trim_start ( ) . split_once ( ' ' ) . unwrap_or ( ( s, "" ) ) ;
108
+ if dev_str. is_empty ( ) {
109
+ return Err ( "Couldn't find dev" ) ;
110
+ }
111
+
112
+ let ( inode_str, s) = s. trim_start ( ) . split_once ( ' ' ) . unwrap_or ( ( s, "" ) ) ;
113
+ if inode_str. is_empty ( ) {
114
+ return Err ( "Couldn't find inode" ) ;
115
+ }
116
+
117
+ // Pathname may be omitted in which case it will be empty
118
+ let pathname_str = s. trim_start ( ) ;
98
119
99
120
let hex = |s| usize:: from_str_radix ( s, 16 ) . map_err ( |_| "Couldn't parse hex number" ) ;
100
121
let address = if let Some ( ( start, limit) ) = range_str. split_once ( '-' ) {
@@ -229,4 +250,46 @@ fn check_maps_entry_parsing_32bit() {
229
250
pathname: Default :: default ( ) ,
230
251
}
231
252
) ;
253
+ assert_eq ! (
254
+ "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
255
+ /executable/path/with some spaces"
256
+ . parse:: <MapsEntry >( )
257
+ . unwrap( ) ,
258
+ MapsEntry {
259
+ address: ( 0xb7c79000 , 0xb7e02000 ) ,
260
+ perms: [ 'r' , '-' , '-' , 'p' ] ,
261
+ offset: 0x00000000 ,
262
+ dev: ( 0x08 , 0x01 ) ,
263
+ inode: 0x60662705 ,
264
+ pathname: "/executable/path/with some spaces" . into( ) ,
265
+ }
266
+ ) ;
267
+ assert_eq ! (
268
+ "b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
269
+ /executable/path/with multiple-continuous spaces "
270
+ . parse:: <MapsEntry >( )
271
+ . unwrap( ) ,
272
+ MapsEntry {
273
+ address: ( 0xb7c79000 , 0xb7e02000 ) ,
274
+ perms: [ 'r' , '-' , '-' , 'p' ] ,
275
+ offset: 0x00000000 ,
276
+ dev: ( 0x08 , 0x01 ) ,
277
+ inode: 0x60662705 ,
278
+ pathname: "/executable/path/with multiple-continuous spaces " . into( ) ,
279
+ }
280
+ ) ;
281
+ assert_eq ! (
282
+ " b7c79000-b7e02000 r--p 00000000 08:01 60662705 \
283
+ /executable/path/starts-with-spaces"
284
+ . parse:: <MapsEntry >( )
285
+ . unwrap( ) ,
286
+ MapsEntry {
287
+ address: ( 0xb7c79000 , 0xb7e02000 ) ,
288
+ perms: [ 'r' , '-' , '-' , 'p' ] ,
289
+ offset: 0x00000000 ,
290
+ dev: ( 0x08 , 0x01 ) ,
291
+ inode: 0x60662705 ,
292
+ pathname: "/executable/path/starts-with-spaces" . into( ) ,
293
+ }
294
+ ) ;
232
295
}
0 commit comments