summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2020-02-15 09:45:38 +0100
committerGitHub <noreply@github.com>2020-02-15 09:45:38 +0100
commitd28b35812fe6e72c8a499dee73e6687816fe829a (patch)
treef82d061b47974ca98fbe81e5754c6d6a2b1cb70a
parentAuto merge of #67681 - matthewjasper:infer-regions-in-borrowck, r=nikomatsakis (diff)
parentAdded From<Vec<NonZeroU8>> for CString (diff)
downloadrust-d28b35812fe6e72c8a499dee73e6687816fe829a.tar.gz
rust-d28b35812fe6e72c8a499dee73e6687816fe829a.tar.bz2
rust-d28b35812fe6e72c8a499dee73e6687816fe829a.tar.xz
Rollup merge of #64069 - danielhenrymantilla:feature/cstring_from_vec_of_nonzerou8, r=KodrAus
Added From<Vec<NonZeroU8>> for CString Added a `From<Vec<NonZeroU8>>` `impl` for `CString` # Rationale - `CString::from_vec_unchecked` is a subtle function, that makes `unsafe` code harder to audit when the generated `Vec`'s creation is non-trivial. This `impl` allows to write safer `unsafe` code thanks to the very explicit semantics of the `Vec<NonZeroU8>` type. - One such situation is when trying to `.read()` a `CString`, see issue #59229. - this lead to a PR: #59314, that was closed for being too specific / narrow (it only targetted being able to `.read()` a `CString`, when this pattern could have been generalized). - the issue suggested another route, based on `From<Vec<NonZeroU8>>`, which is indeed a less general and more concise code pattern. - quoting @shnatsel: - > For me the main thing about making this safe is simplifying auditing - people have spent like an hour looking at just this one unsafe block in libflate because it's not clear what exactly is unchecked, so you have to look it up when auditing anyway. This has distracted us from much more serious memory safety issues the library had. Having this trivial impl in stdlib would turn this into safe code with compiler more or less guaranteeing that it's fine, and save anyone auditing the code a whole lot of time.
-rw-r--r--src/libstd/ffi/c_str.rs27
-rw-r--r--src/libstd/lib.rs1
2 files changed, 28 insertions, 0 deletions
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index 700e015..04eaba5 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -6,6 +6,7 @@ use crate::fmt::{self, Write};
6use crate::io; 6use crate::io;
7use crate::mem; 7use crate::mem;
8use crate::memchr; 8use crate::memchr;
9use crate::num::NonZeroU8;
9use crate::ops; 10use crate::ops;
10use crate::os::raw::c_char; 11use crate::os::raw::c_char;
11use crate::ptr; 12use crate::ptr;
@@ -741,6 +742,32 @@ impl From<Box<CStr>> for CString {
741 } 742 }
742} 743}
743 744
745#[stable(feature = "cstring_from_vec_of_nonzerou8", since = "1.43.0")]
746impl From<Vec<NonZeroU8>> for CString {
747 /// Converts a [`Vec`]`<`[`NonZeroU8`]`>` into a [`CString`] without
748 /// copying nor checking for inner null bytes.
749 ///
750 /// [`CString`]: ../ffi/struct.CString.html
751 /// [`NonZeroU8`]: ../num/struct.NonZeroU8.html
752 /// [`Vec`]: ../vec/struct.Vec.html
753 #[inline]
754 fn from(v: Vec<NonZeroU8>) -> CString {
755 unsafe {
756 // Transmute `Vec<NonZeroU8>` to `Vec<u8>`.
757 let v: Vec<u8> = {
758 // Safety:
759 // - transmuting between `NonZeroU8` and `u8` is sound;
760 // - `alloc::Layout<NonZeroU8> == alloc::Layout<u8>`.
761 let (ptr, len, cap): (*mut NonZeroU8, _, _) = Vec::into_raw_parts(v);
762 Vec::from_raw_parts(ptr.cast::<u8>(), len, cap)
763 };
764 // Safety: `v` cannot contain null bytes, given the type-level
765 // invariant of `NonZeroU8`.
766 CString::from_vec_unchecked(v)
767 }
768 }
769}
770
744#[stable(feature = "more_box_slice_clone", since = "1.29.0")] 771#[stable(feature = "more_box_slice_clone", since = "1.29.0")]
745impl Clone for Box<CStr> { 772impl Clone for Box<CStr> {
746 #[inline] 773 #[inline]
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index f9c9f22..799585f 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -309,6 +309,7 @@
309#![feature(unboxed_closures)] 309#![feature(unboxed_closures)]
310#![feature(untagged_unions)] 310#![feature(untagged_unions)]
311#![feature(unwind_attributes)] 311#![feature(unwind_attributes)]
312#![feature(vec_into_raw_parts)]
312// NB: the above list is sorted to minimize merge conflicts. 313// NB: the above list is sorted to minimize merge conflicts.
313#![default_lib_allocator] 314#![default_lib_allocator]
314 315