Skip to content

Commit 272cd38

Browse files
committed
Fall back to an unoptimized implementation in read_binary_file if File::metadata lies
1 parent 55e5c9d commit 272cd38

File tree

1 file changed

+31
-2
lines changed

1 file changed

+31
-2
lines changed

Diff for: compiler/rustc_span/src/source_map.rs

+31-2
Original file line numberDiff line numberDiff line change
@@ -127,10 +127,39 @@ impl FileLoader for RealFileLoader {
127127

128128
let mut bytes = Lrc::new_uninit_slice(len as usize);
129129
let mut buf = BorrowedBuf::from(Lrc::get_mut(&mut bytes).unwrap());
130-
file.read_buf_exact(buf.unfilled())?;
130+
match file.read_buf_exact(buf.unfilled()) {
131+
Ok(()) => {}
132+
Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => {
133+
drop(bytes);
134+
return fs::read(path).map(Vec::into);
135+
}
136+
Err(e) => return Err(e),
137+
}
131138
// SAFETY: If the read_buf_exact call returns Ok(()), then we have
132139
// read len bytes and initialized the buffer.
133-
Ok(unsafe { bytes.assume_init() })
140+
let bytes = unsafe { bytes.assume_init() };
141+
142+
// At this point, we've read all the bytes that filesystem metadata reported exist.
143+
// But we are not guaranteed to be at the end of the file, because we did not attempt to do
144+
// a read with a non-zero-sized buffer and get Ok(0).
145+
// So we do small read to a fixed-size buffer. If the read returns no bytes then we're
146+
// already done, and we just return the Lrc we built above.
147+
// If the read returns bytes however, we just fall back to reading into a Vec then turning
148+
// that into an Lrc, losing our nice peak memory behavior. This fallback code path should
149+
// be rarely exercised.
150+
151+
let mut probe = [0u8; 32];
152+
let n = loop {
153+
match file.read(&mut probe) {
154+
Ok(0) => return Ok(bytes),
155+
Err(e) if e.kind() == io::ErrorKind::Interrupted => continue,
156+
Err(e) => return Err(e),
157+
Ok(n) => break n,
158+
}
159+
};
160+
let mut bytes: Vec<u8> = bytes.iter().copied().chain(probe[..n].iter().copied()).collect();
161+
file.read_to_end(&mut bytes)?;
162+
Ok(bytes.into())
134163
}
135164
}
136165

0 commit comments

Comments
 (0)