@@ -19,6 +19,7 @@ use mem;
1919use memchr;
2020use ops;
2121use os:: raw:: c_char;
22+ use ptr;
2223use slice;
2324use str:: { self , Utf8Error } ;
2425
@@ -68,6 +69,9 @@ use str::{self, Utf8Error};
6869#[ derive( PartialEq , PartialOrd , Eq , Ord , Hash , Clone ) ]
6970#[ stable( feature = "rust1" , since = "1.0.0" ) ]
7071pub struct CString {
72+ // Invariant 1: the slice ends with a zero byte and has a length of at least one.
73+ // Invariant 2: the slice contains only one zero byte.
74+ // Improper usage of unsafe function can break Invariant 2, but not Invariant 1.
7175 inner : Box < [ u8 ] > ,
7276}
7377
@@ -244,7 +248,7 @@ impl CString {
244248 /// Failure to call `from_raw` will lead to a memory leak.
245249 #[ stable( feature = "cstr_memory" , since = "1.4.0" ) ]
246250 pub fn into_raw ( self ) -> * mut c_char {
247- Box :: into_raw ( self . inner ) as * mut c_char
251+ Box :: into_raw ( self . into_inner ( ) ) as * mut c_char
248252 }
249253
250254 /// Converts the `CString` into a `String` if it contains valid Unicode data.
@@ -265,7 +269,7 @@ impl CString {
265269 /// it is guaranteed to not have any interior nul bytes.
266270 #[ stable( feature = "cstring_into" , since = "1.7.0" ) ]
267271 pub fn into_bytes ( self ) -> Vec < u8 > {
268- let mut vec = self . inner . into_vec ( ) ;
272+ let mut vec = self . into_inner ( ) . into_vec ( ) ;
269273 let _nul = vec. pop ( ) ;
270274 debug_assert_eq ! ( _nul, Some ( 0u8 ) ) ;
271275 vec
@@ -275,7 +279,7 @@ impl CString {
275279 /// includes the trailing nul byte.
276280 #[ stable( feature = "cstring_into" , since = "1.7.0" ) ]
277281 pub fn into_bytes_with_nul ( self ) -> Vec < u8 > {
278- self . inner . into_vec ( )
282+ self . into_inner ( ) . into_vec ( )
279283 }
280284
281285 /// Returns the contents of this `CString` as a slice of bytes.
@@ -293,6 +297,24 @@ impl CString {
293297 pub fn as_bytes_with_nul ( & self ) -> & [ u8 ] {
294298 & self . inner
295299 }
300+
301+ // Bypass "move out of struct which implements `Drop` trait" restriction.
302+ fn into_inner ( self ) -> Box < [ u8 ] > {
303+ unsafe {
304+ let result = ptr:: read ( & self . inner ) ;
305+ mem:: forget ( self ) ;
306+ result
307+ }
308+ }
309+ }
310+
311+ // Turns this `CString` into an empty string to prevent
312+ // memory unsafe code from working by accident.
313+ #[ stable( feature = "cstring_drop" , since = "1.13.0" ) ]
314+ impl Drop for CString {
315+ fn drop ( & mut self ) {
316+ unsafe { * self . inner . get_unchecked_mut ( 0 ) = 0 ; }
317+ }
296318}
297319
298320#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments