Skip to content

Commit 6294cb5

Browse files
committed
Corrects /proc/pid/maps parser to correctly handle spaces in pathnames
1 parent 0533d47 commit 6294cb5

File tree

1 file changed

+54
-9
lines changed

1 file changed

+54
-9
lines changed

src/symbolize/gimli/parse_running_mmaps_unix.rs

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)