@@ -382,7 +382,7 @@ impl CString {
382382 let bytes: Vec < u8 > = self . into ( ) ;
383383 match memchr:: memchr ( 0 , & bytes) {
384384 Some ( i) => Err ( NulError ( i, bytes) ) ,
385- None => Ok ( unsafe { CString :: from_vec_unchecked ( bytes) } ) ,
385+ None => Ok ( unsafe { CString :: _from_vec_unchecked ( bytes) } ) ,
386386 }
387387 }
388388 }
@@ -405,7 +405,7 @@ impl CString {
405405 // This allows better optimizations if lto enabled.
406406 match memchr:: memchr ( 0 , bytes) {
407407 Some ( i) => Err ( NulError ( i, buffer) ) ,
408- None => Ok ( unsafe { CString :: from_vec_unchecked ( buffer) } ) ,
408+ None => Ok ( unsafe { CString :: _from_vec_unchecked ( buffer) } ) ,
409409 }
410410 }
411411
@@ -451,10 +451,15 @@ impl CString {
451451 /// ```
452452 #[ must_use]
453453 #[ stable( feature = "rust1" , since = "1.0.0" ) ]
454- pub unsafe fn from_vec_unchecked ( mut v : Vec < u8 > ) -> CString {
454+ pub unsafe fn from_vec_unchecked ( v : Vec < u8 > ) -> Self {
455+ debug_assert ! ( memchr:: memchr( 0 , & v) . is_none( ) ) ;
456+ unsafe { Self :: _from_vec_unchecked ( v) }
457+ }
458+
459+ unsafe fn _from_vec_unchecked ( mut v : Vec < u8 > ) -> Self {
455460 v. reserve_exact ( 1 ) ;
456461 v. push ( 0 ) ;
457- CString { inner : v. into_boxed_slice ( ) }
462+ Self { inner : v. into_boxed_slice ( ) }
458463 }
459464
460465 /// Retakes ownership of a `CString` that was transferred to C via
@@ -578,7 +583,7 @@ impl CString {
578583 pub fn into_string ( self ) -> Result < String , IntoStringError > {
579584 String :: from_utf8 ( self . into_bytes ( ) ) . map_err ( |e| IntoStringError {
580585 error : e. utf8_error ( ) ,
581- inner : unsafe { CString :: from_vec_unchecked ( e. into_bytes ( ) ) } ,
586+ inner : unsafe { Self :: _from_vec_unchecked ( e. into_bytes ( ) ) } ,
582587 } )
583588 }
584589
@@ -735,6 +740,11 @@ impl CString {
735740 #[ must_use]
736741 #[ stable( feature = "cstring_from_vec_with_nul" , since = "1.58.0" ) ]
737742 pub unsafe fn from_vec_with_nul_unchecked ( v : Vec < u8 > ) -> Self {
743+ debug_assert ! ( memchr:: memchr( 0 , & v) . unwrap( ) + 1 == v. len( ) ) ;
744+ unsafe { Self :: _from_vec_with_nul_unchecked ( v) }
745+ }
746+
747+ unsafe fn _from_vec_with_nul_unchecked ( v : Vec < u8 > ) -> Self {
738748 Self { inner : v. into_boxed_slice ( ) }
739749 }
740750
@@ -778,7 +788,7 @@ impl CString {
778788 Some ( nul_pos) if nul_pos + 1 == v. len ( ) => {
779789 // SAFETY: We know there is only one nul byte, at the end
780790 // of the vec.
781- Ok ( unsafe { Self :: from_vec_with_nul_unchecked ( v) } )
791+ Ok ( unsafe { Self :: _from_vec_with_nul_unchecked ( v) } )
782792 }
783793 Some ( nul_pos) => Err ( FromVecWithNulError {
784794 error_kind : FromBytesWithNulErrorKind :: InteriorNul ( nul_pos) ,
@@ -811,7 +821,7 @@ impl ops::Deref for CString {
811821
812822 #[ inline]
813823 fn deref ( & self ) -> & CStr {
814- unsafe { CStr :: from_bytes_with_nul_unchecked ( self . as_bytes_with_nul ( ) ) }
824+ unsafe { CStr :: _from_bytes_with_nul_unchecked ( self . as_bytes_with_nul ( ) ) }
815825 }
816826}
817827
@@ -928,7 +938,7 @@ impl From<Vec<NonZeroU8>> for CString {
928938 } ;
929939 // SAFETY: `v` cannot contain null bytes, given the type-level
930940 // invariant of `NonZeroU8`.
931- CString :: from_vec_unchecked ( v)
941+ Self :: _from_vec_unchecked ( v)
932942 }
933943 }
934944}
@@ -1225,7 +1235,7 @@ impl CStr {
12251235 unsafe {
12261236 let len = sys:: strlen ( ptr) ;
12271237 let ptr = ptr as * const u8 ;
1228- CStr :: from_bytes_with_nul_unchecked ( slice:: from_raw_parts ( ptr, len as usize + 1 ) )
1238+ Self :: _from_bytes_with_nul_unchecked ( slice:: from_raw_parts ( ptr, len as usize + 1 ) )
12291239 }
12301240 }
12311241
@@ -1268,7 +1278,7 @@ impl CStr {
12681278 Some ( nul_pos) if nul_pos + 1 == bytes. len ( ) => {
12691279 // SAFETY: We know there is only one nul byte, at the end
12701280 // of the byte slice.
1271- Ok ( unsafe { Self :: from_bytes_with_nul_unchecked ( bytes) } )
1281+ Ok ( unsafe { Self :: _from_bytes_with_nul_unchecked ( bytes) } )
12721282 }
12731283 Some ( nul_pos) => Err ( FromBytesWithNulError :: interior_nul ( nul_pos) ) ,
12741284 None => Err ( FromBytesWithNulError :: not_nul_terminated ( ) ) ,
@@ -1297,12 +1307,19 @@ impl CStr {
12971307 #[ stable( feature = "cstr_from_bytes" , since = "1.10.0" ) ]
12981308 #[ rustc_const_stable( feature = "const_cstr_unchecked" , since = "1.59.0" ) ]
12991309 pub const unsafe fn from_bytes_with_nul_unchecked ( bytes : & [ u8 ] ) -> & CStr {
1310+ // We're in a const fn, so this is the best we can do
1311+ debug_assert ! ( !bytes. is_empty( ) && bytes[ bytes. len( ) - 1 ] == 0 ) ;
1312+ unsafe { Self :: _from_bytes_with_nul_unchecked ( bytes) }
1313+ }
1314+
1315+ #[ inline]
1316+ const unsafe fn _from_bytes_with_nul_unchecked ( bytes : & [ u8 ] ) -> & Self {
13001317 // SAFETY: Casting to CStr is safe because its internal representation
13011318 // is a [u8] too (safe only inside std).
13021319 // Dereferencing the obtained pointer is safe because it comes from a
13031320 // reference. Making a reference is then safe because its lifetime
13041321 // is bound by the lifetime of the given `bytes`.
1305- unsafe { & * ( bytes as * const [ u8 ] as * const CStr ) }
1322+ unsafe { & * ( bytes as * const [ u8 ] as * const Self ) }
13061323 }
13071324
13081325 /// Returns the inner pointer to this C string.
@@ -1566,7 +1583,7 @@ impl ops::Index<ops::RangeFrom<usize>> for CStr {
15661583 // byte, since otherwise we could get an empty string that doesn't end
15671584 // in a null.
15681585 if index. start < bytes. len ( ) {
1569- unsafe { CStr :: from_bytes_with_nul_unchecked ( & bytes[ index. start ..] ) }
1586+ unsafe { CStr :: _from_bytes_with_nul_unchecked ( & bytes[ index. start ..] ) }
15701587 } else {
15711588 panic ! (
15721589 "index out of bounds: the len is {} but the index is {}" ,
0 commit comments