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

7 files changed

lines changed

Original file line number Diff line number Diff line change
@@ -533,6 +533,25 @@ impl OsString {
533 533 unsafe { Box::from_raw(rw) }
534 534 }
535 535
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 +
536 555 /// Part of a hack to make PathBuf::push/pop more efficient.
537 556 #[inline]
538 557 pub(crate) fn as_mut_vec_for_path_buf(&mut self) -> &mut Vec<u8> {
Original file line number Diff line number Diff line change
@@ -23,6 +23,15 @@ fn test_os_string_clear() {
23 23 assert_eq!(0, os_string.inner.as_inner().len());
24 24 }
25 25
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 +
26 35 #[test]
27 36 fn test_os_string_capacity() {
28 37 let os_string = OsString::with_capacity(0);
Original file line number Diff line number Diff line change
@@ -1226,6 +1226,25 @@ impl PathBuf {
1226 1226 self
1227 1227 }
1228 1228
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 +
1229 1248 /// Extends `self` with `path`.
1230 1249 ///
1231 1250 /// If `path` is absolute, it replaces the current path.
Original file line number Diff line number Diff line change
@@ -126,6 +126,16 @@ fn into() {
126 126 assert_eq!(static_cow_path, owned_cow_path);
127 127 }
128 128
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 +
129 139 #[test]
130 140 #[cfg(unix)]
131 141 pub fn test_decompositions_unix() {
Original file line number Diff line number Diff line change
@@ -176,6 +176,11 @@ impl Buf {
176 176 self.inner.extend_from_slice(&s.inner)
177 177 }
178 178
179 +#[inline]
180 +pub fn leak<'a>(self) -> &'a mut Slice {
181 +unsafe { mem::transmute(self.inner.leak()) }
182 +}
183 +
179 184 #[inline]
180 185 pub fn into_box(self) -> Box<Slice> {
181 186 unsafe { mem::transmute(self.inner.into_boxed_slice()) }
Original file line number Diff line number Diff line change
@@ -138,6 +138,11 @@ impl Buf {
138 138 self.inner.shrink_to(min_capacity)
139 139 }
140 140
141 +#[inline]
142 +pub fn leak<'a>(self) -> &'a mut Slice {
143 +unsafe { mem::transmute(self.inner.leak()) }
144 +}
145 +
141 146 #[inline]
142 147 pub fn into_box(self) -> Box<Slice> {
143 148 unsafe { mem::transmute(self.inner.into_box()) }
Original file line number Diff line number Diff line change
@@ -325,6 +325,11 @@ impl Wtf8Buf {
325 325 self.bytes.shrink_to(min_capacity)
326 326 }
327 327
328 +#[inline]
329 +pub fn leak<'a>(self) -> &'a mut Wtf8 {
330 +unsafe { Wtf8::from_mut_bytes_unchecked(self.bytes.leak()) }
331 +}
332 +
328 333 /// Returns the number of bytes that this string buffer can hold without reallocating.
329 334 #[inline]
330 335 pub fn capacity(&self) -> usize {