Skip to content

Commit c8b79dd

Browse files
committed
Use ManuallyDrop in BufWriter::into_parts
1 parent 0476fc4 commit c8b79dd

File tree

2 files changed

+17
-7
lines changed

2 files changed

+17
-7
lines changed

std/src/io/buffered/bufwriter.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use crate::fmt;
33
use crate::io::{
44
self, ErrorKind, IntoInnerError, IoSlice, Seek, SeekFrom, Write, DEFAULT_BUF_SIZE,
55
};
6-
use crate::mem;
6+
use crate::mem::{self, ManuallyDrop};
77
use crate::ptr;
88

99
/// Wraps a writer and buffers its output.
@@ -164,13 +164,13 @@ impl<W: Write> BufWriter<W> {
164164
/// assert_eq!(&buffered_data.unwrap(), b"ata");
165165
/// ```
166166
#[stable(feature = "bufwriter_into_parts", since = "1.56.0")]
167-
pub fn into_parts(mut self) -> (W, Result<Vec<u8>, WriterPanicked>) {
168-
let buf = mem::take(&mut self.buf);
169-
let buf = if !self.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
167+
pub fn into_parts(self) -> (W, Result<Vec<u8>, WriterPanicked>) {
168+
let mut this = ManuallyDrop::new(self);
169+
let buf = mem::take(&mut this.buf);
170+
let buf = if !this.panicked { Ok(buf) } else { Err(WriterPanicked { buf }) };
170171

171-
// SAFETY: forget(self) prevents double dropping inner
172-
let inner = unsafe { ptr::read(&self.inner) };
173-
mem::forget(self);
172+
// SAFETY: double-drops are prevented by putting `this` in a ManuallyDrop that is never dropped
173+
let inner = unsafe { ptr::read(&this.inner) };
174174

175175
(inner, buf)
176176
}

std/src/io/buffered/tests.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1067,3 +1067,13 @@ fn bufreader_full_initialize() {
10671067
// But we initialized the whole buffer!
10681068
assert_eq!(reader.initialized(), reader.capacity());
10691069
}
1070+
1071+
/// This is a regression test for https://github.com/rust-lang/rust/issues/127584.
1072+
#[test]
1073+
fn bufwriter_aliasing() {
1074+
use crate::io::{BufWriter, Cursor};
1075+
let mut v = vec![0; 1024];
1076+
let c = Cursor::new(&mut v);
1077+
let w = BufWriter::new(Box::new(c));
1078+
let _ = w.into_parts();
1079+
}

0 commit comments

Comments
 (0)