diff options
| author | bors <bors@rust-lang.org> | 2023-09-21 02:50:54 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2023-09-21 02:50:54 +0000 |
| commit | 4fda889bf8735755573b27e6116ce025f3ded5f9 (patch) | |
| tree | 320dfacc8bd8990b5a8e046f48a7cf6131ec11ff /compiler/rustc_span/src/source_map.rs | |
| parent | cbce15c6173cd0fcd4abe25c108067d32f1135b4 (diff) | |
| parent | 5f33647fb392c2d4f71af94a223bc1a9abb80643 (diff) | |
| download | rust-4fda889bf8735755573b27e6116ce025f3ded5f9.tar.gz rust-4fda889bf8735755573b27e6116ce025f3ded5f9.zip | |
Auto merge of #115549 - saethlin:include-bytes-resilient, r=jackh726
Fall back to the unoptimized implementation in read_binary_file if File::metadata lies Fixes https://github.com/rust-lang/rust/issues/115458 r? `@jackh726` because you approved the previous PR
Diffstat (limited to 'compiler/rustc_span/src/source_map.rs')
| -rw-r--r-- | compiler/rustc_span/src/source_map.rs | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs index 68727a6c40e..0b575c13adf 100644 --- a/compiler/rustc_span/src/source_map.rs +++ b/compiler/rustc_span/src/source_map.rs @@ -127,10 +127,39 @@ impl FileLoader for RealFileLoader { let mut bytes = Lrc::new_uninit_slice(len as usize); let mut buf = BorrowedBuf::from(Lrc::get_mut(&mut bytes).unwrap()); - file.read_buf_exact(buf.unfilled())?; + match file.read_buf_exact(buf.unfilled()) { + Ok(()) => {} + Err(e) if e.kind() == io::ErrorKind::UnexpectedEof => { + drop(bytes); + return fs::read(path).map(Vec::into); + } + Err(e) => return Err(e), + } // SAFETY: If the read_buf_exact call returns Ok(()), then we have // read len bytes and initialized the buffer. - Ok(unsafe { bytes.assume_init() }) + let bytes = unsafe { bytes.assume_init() }; + + // At this point, we've read all the bytes that filesystem metadata reported exist. + // But we are not guaranteed to be at the end of the file, because we did not attempt to do + // a read with a non-zero-sized buffer and get Ok(0). + // So we do small read to a fixed-size buffer. If the read returns no bytes then we're + // already done, and we just return the Lrc we built above. + // If the read returns bytes however, we just fall back to reading into a Vec then turning + // that into an Lrc, losing our nice peak memory behavior. This fallback code path should + // be rarely exercised. + + let mut probe = [0u8; 32]; + let n = loop { + match file.read(&mut probe) { + Ok(0) => return Ok(bytes), + Err(e) if e.kind() == io::ErrorKind::Interrupted => continue, + Err(e) => return Err(e), + Ok(n) => break n, + } + }; + let mut bytes: Vec<u8> = bytes.iter().copied().chain(probe[..n].iter().copied()).collect(); + file.read_to_end(&mut bytes)?; + Ok(bytes.into()) } } |
