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 { |