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