@@ -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
@@ -922,7 +932,7 @@ impl From<Vec<NonZeroU8>> for CString {
922932 } ;
923933 // SAFETY: `v` cannot contain null bytes, given the type-level
924934 // invariant of `NonZeroU8`.
925- CString :: from_vec_unchecked ( v)
935+ Self :: _from_vec_unchecked ( v)
926936 }
927937 }
928938}
@@ -1215,7 +1225,7 @@ impl CStr {
12151225 unsafe {
12161226 let len = sys:: strlen ( ptr) ;
12171227 let ptr = ptr as * const u8 ;
1218- CStr :: from_bytes_with_nul_unchecked ( slice:: from_raw_parts ( ptr, len as usize + 1 ) )
1228+ Self :: _from_bytes_with_nul_unchecked ( slice:: from_raw_parts ( ptr, len as usize + 1 ) )
12191229 }
12201230 }
12211231
@@ -1258,7 +1268,7 @@ impl CStr {
12581268 Some ( nul_pos) if nul_pos + 1 == bytes. len ( ) => {
12591269 // SAFETY: We know there is only one nul byte, at the end
12601270 // of the byte slice.
1261- Ok ( unsafe { Self :: from_bytes_with_nul_unchecked ( bytes) } )
1271+ Ok ( unsafe { Self :: _from_bytes_with_nul_unchecked ( bytes) } )
12621272 }
12631273 Some ( nul_pos) => Err ( FromBytesWithNulError :: interior_nul ( nul_pos) ) ,
12641274 None => Err ( FromBytesWithNulError :: not_nul_terminated ( ) ) ,
@@ -1287,12 +1297,19 @@ impl CStr {
12871297 #[ stable( feature = "cstr_from_bytes" , since = "1.10.0" ) ]
12881298 #[ rustc_const_stable( feature = "const_cstr_unchecked" , since = "1.59.0" ) ]
12891299 pub const unsafe fn from_bytes_with_nul_unchecked ( bytes : & [ u8 ] ) -> & CStr {
1300+ // We're in a const fn, so this is the best we can do
1301+ debug_assert ! ( !bytes. is_empty( ) && bytes[ bytes. len( ) - 1 ] == 0 ) ;
1302+ unsafe { Self :: _from_bytes_with_nul_unchecked ( bytes) }
1303+ }
1304+
1305+ #[ inline]
1306+ const unsafe fn _from_bytes_with_nul_unchecked ( bytes : & [ u8 ] ) -> & Self {
12901307 // SAFETY: Casting to CStr is safe because its internal representation
12911308 // is a [u8] too (safe only inside std).
12921309 // Dereferencing the obtained pointer is safe because it comes from a
12931310 // reference. Making a reference is then safe because its lifetime
12941311 // is bound by the lifetime of the given `bytes`.
1295- unsafe { & * ( bytes as * const [ u8 ] as * const CStr ) }
1312+ unsafe { & * ( bytes as * const [ u8 ] as * const Self ) }
12961313 }
12971314
12981315 /// Returns the inner pointer to this C string.
@@ -1555,7 +1572,7 @@ impl ops::Index<ops::RangeFrom<usize>> for CStr {
15551572 // byte, since otherwise we could get an empty string that doesn't end
15561573 // in a null.
15571574 if index. start < bytes. len ( ) {
1558- unsafe { CStr :: from_bytes_with_nul_unchecked ( & bytes[ index. start ..] ) }
1575+ unsafe { CStr :: _from_bytes_with_nul_unchecked ( & bytes[ index. start ..] ) }
15591576 } else {
15601577 panic ! (
15611578 "index out of bounds: the len is {} but the index is {}" ,
0 commit comments