Auto merge of #125966 - schvv31n:impl_os_string_pathbuf_leak, r=worki… · model-checking/verify-rust-std@e6c378f

7 files changed

lines changed

Original file line numberDiff line numberDiff line change

@@ -533,6 +533,25 @@ impl OsString {

533533

unsafe { Box::from_raw(rw) }

534534

}

535535
536+

/// Consumes and leaks the `OsString`, returning a mutable reference to the contents,

537+

/// `&'a mut OsStr`.

538+

///

539+

/// The caller has free choice over the returned lifetime, including 'static.

540+

/// Indeed, this function is ideally used for data that lives for the remainder of

541+

/// the program’s life, as dropping the returned reference will cause a memory leak.

542+

///

543+

/// It does not reallocate or shrink the `OsString`, so the leaked allocation may include

544+

/// unused capacity that is not part of the returned slice. If you want to discard excess

545+

/// capacity, call [`into_boxed_os_str`], and then [`Box::leak`] instead.

546+

/// However, keep in mind that trimming the capacity may result in a reallocation and copy.

547+

///

548+

/// [`into_boxed_os_str`]: Self::into_boxed_os_str

549+

#[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]

550+

#[inline]

551+

pub fn leak<'a>(self) -> &'a mut OsStr {

552+

OsStr::from_inner_mut(self.inner.leak())

553+

}

554+
536555

/// Part of a hack to make PathBuf::push/pop more efficient.

537556

#[inline]

538557

pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec<u8> {

Original file line numberDiff line numberDiff line change

@@ -23,6 +23,15 @@ fn test_os_string_clear() {

2323

assert_eq!(0, os_string.inner.as_inner().len());

2424

}

2525
26+

#[test]

27+

fn test_os_string_leak() {

28+

let os_string = OsString::from("have a cake");

29+

let (len, cap) = (os_string.len(), os_string.capacity());

30+

let leaked = os_string.leak();

31+

assert_eq!(leaked.as_encoded_bytes(), b"have a cake");

32+

unsafe { drop(String::from_raw_parts(leaked as *mut OsStr as _, len, cap)) }

33+

}

34+
2635

#[test]

2736

fn test_os_string_capacity() {

2837

let os_string = OsString::with_capacity(0);

Original file line numberDiff line numberDiff line change

@@ -1226,6 +1226,25 @@ impl PathBuf {

12261226

self

12271227

}

12281228
1229+

/// Consumes and leaks the `PathBuf`, returning a mutable reference to the contents,

1230+

/// `&'a mut Path`.

1231+

///

1232+

/// The caller has free choice over the returned lifetime, including 'static.

1233+

/// Indeed, this function is ideally used for data that lives for the remainder of

1234+

/// the program’s life, as dropping the returned reference will cause a memory leak.

1235+

///

1236+

/// It does not reallocate or shrink the `PathBuf`, so the leaked allocation may include

1237+

/// unused capacity that is not part of the returned slice. If you want to discard excess

1238+

/// capacity, call [`into_boxed_path`], and then [`Box::leak`] instead.

1239+

/// However, keep in mind that trimming the capacity may result in a reallocation and copy.

1240+

///

1241+

/// [`into_boxed_path`]: Self::into_boxed_path

1242+

#[unstable(feature = "os_string_pathbuf_leak", issue = "125965")]

1243+

#[inline]

1244+

pub fn leak<'a>(self) -> &'a mut Path {

1245+

Path::from_inner_mut(self.inner.leak())

1246+

}

1247+
12291248

/// Extends `self` with `path`.

12301249

///

12311250

/// If `path` is absolute, it replaces the current path.

Original file line numberDiff line numberDiff line change

@@ -126,6 +126,16 @@ fn into() {

126126

assert_eq!(static_cow_path, owned_cow_path);

127127

}

128128
129+

#[test]

130+

fn test_pathbuf_leak() {

131+

let string = "/have/a/cake".to_owned();

132+

let (len, cap) = (string.len(), string.capacity());

133+

let buf = PathBuf::from(string);

134+

let leaked = buf.leak();

135+

assert_eq!(leaked.as_os_str().as_encoded_bytes(), b"/have/a/cake");

136+

unsafe { drop(String::from_raw_parts(leaked.as_mut_os_str() as *mut OsStr as _, len, cap)) }

137+

}

138+
129139

#[test]

130140

#[cfg(unix)]

131141

pub fn test_decompositions_unix() {

Original file line numberDiff line numberDiff line change

@@ -176,6 +176,11 @@ impl Buf {

176176

self.inner.extend_from_slice(&s.inner)

177177

}

178178
179+

#[inline]

180+

pub fn leak<'a>(self) -> &'a mut Slice {

181+

unsafe { mem::transmute(self.inner.leak()) }

182+

}

183+
179184

#[inline]

180185

pub fn into_box(self) -> Box<Slice> {

181186

unsafe { mem::transmute(self.inner.into_boxed_slice()) }

Original file line numberDiff line numberDiff line change

@@ -138,6 +138,11 @@ impl Buf {

138138

self.inner.shrink_to(min_capacity)

139139

}

140140
141+

#[inline]

142+

pub fn leak<'a>(self) -> &'a mut Slice {

143+

unsafe { mem::transmute(self.inner.leak()) }

144+

}

145+
141146

#[inline]

142147

pub fn into_box(self) -> Box<Slice> {

143148

unsafe { mem::transmute(self.inner.into_box()) }

Original file line numberDiff line numberDiff line change

@@ -325,6 +325,11 @@ impl Wtf8Buf {

325325

self.bytes.shrink_to(min_capacity)

326326

}

327327
328+

#[inline]

329+

pub fn leak<'a>(self) -> &'a mut Wtf8 {

330+

unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) }

331+

}

332+
328333

/// Returns the number of bytes that this string buffer can hold without reallocating.

329334

#[inline]

330335

pub fn capacity(&self) -> usize {