Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions library/alloc/src/vec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1784,6 +1784,9 @@ impl<T, A: Allocator> Vec<T, A> {
/// [`drain`]: Vec::drain
#[stable(feature = "rust1", since = "1.0.0")]
pub fn truncate(&mut self, len: usize) {
// SAFETY: `BufWriter::flush_buf` assumes that this will not
// de-initialize any elements of the spare capacity.

// This is safe because:
//
// * the slice passed to `drop_in_place` is valid; the `len > self.len`
Expand Down Expand Up @@ -1857,6 +1860,9 @@ impl<T, A: Allocator> Vec<T, A> {
#[rustc_diagnostic_item = "vec_as_mut_slice"]
#[rustc_const_stable(feature = "const_vec_string_slice", since = "1.87.0")]
pub const fn as_mut_slice(&mut self) -> &mut [T] {
// SAFETY: `BufWriter::flush_buf` assumes that this will not
// de-initialize any elements of the spare capacity.

// SAFETY: `slice::from_raw_parts_mut` requires pointee is a contiguous, aligned buffer of
// size `len` containing properly-initialized `T`s. Data must not be accessed through any
// other pointer for the returned lifetime. Further, `len * size_of::<T>` <=
Expand Down
2 changes: 1 addition & 1 deletion library/core/src/io/borrowed_buf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ impl<'data> BorrowedBuf<'data> {
self.filled
}

/// Returns the length of the initialized part of the buffer.
/// Returns `true` if the buffer is initialized.
#[unstable(feature = "borrowed_buf_init", issue = "78485")]
#[inline]
pub fn is_init(&self) -> bool {
Expand Down
15 changes: 14 additions & 1 deletion library/std/src/io/buffered/bufwriter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,10 @@ impl<W: ?Sized + Write> BufWriter<W> {
/// `write`), any 0-length writes from `inner` must be reported as i/o
/// errors from this method.
pub(in crate::io) fn flush_buf(&mut self) -> io::Result<()> {
// SAFETY: `<BufWriter as BufferedWriterSpec>::copy_from` assumes that
// this will not de-initialize any elements of `self.buf`'s spare
// capacity.

/// Helper struct to ensure the buffer is updated after all the writes
/// are complete. It tracks the number of written bytes and drains them
/// all from the front of the buffer when dropped.
Expand Down Expand Up @@ -225,7 +229,16 @@ impl<W: ?Sized + Write> BufWriter<W> {
impl Drop for BufGuard<'_> {
fn drop(&mut self) {
if self.written > 0 {
self.buffer.drain(..self.written);
// Like `self.buffer.drain(..self.written)` but more obviously
// preserving the spare capacity; see note above.
let new_len = self.buffer.len() - self.written;
// SAFETY: Assumes `Vec::as_mut_slice` will not
// de-initialize any elements of `self.buf`'s spare capacity,
// and that `<&mut [u8]>::copy_within` will not do so either.
self.buffer.as_mut_slice().copy_within(self.written.., 0);
// SAFETY: Assumes `Vec::truncate` will not de-initialize
// any elements of `self.buf`'s spare capacity,
self.buffer.truncate(new_len);
}
}
}
Expand Down
5 changes: 4 additions & 1 deletion library/std/src/io/copy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,8 @@ impl<I: Write + ?Sized> BufferedWriterSpec for BufWriter<I> {
let mut read_buf: BorrowedBuf<'_> = buf.spare_capacity_mut().into();

if init {
// SAFETY: init is either 0 or the init_len from the previous iteration.
// SAFETY: `init` is only true after `reader` initializes
// `read_buf`. See the comment about `flush_buf` below.
unsafe { read_buf.set_init() };
}

Expand All @@ -248,6 +249,8 @@ impl<I: Write + ?Sized> BufferedWriterSpec for BufWriter<I> {
Err(e) => return Err(e),
}
} else {
// SAFETY: `flush_buf` will not de-initialize any elements of
// the spare capacity so we can remember `init` across this.
self.flush_buf()?;
}
}
Expand Down
Loading