@@ -19,6 +19,7 @@ use mem;
19
19
use memchr;
20
20
use ops;
21
21
use os:: raw:: c_char;
22
+ use ptr;
22
23
use slice;
23
24
use str:: { self , Utf8Error } ;
24
25
@@ -68,6 +69,9 @@ use str::{self, Utf8Error};
68
69
#[ derive( PartialEq , PartialOrd , Eq , Ord , Hash , Clone ) ]
69
70
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
70
71
pub 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.
71
75
inner : Box < [ u8 ] > ,
72
76
}
73
77
@@ -244,7 +248,7 @@ impl CString {
244
248
/// Failure to call `from_raw` will lead to a memory leak.
245
249
#[ stable( feature = "cstr_memory" , since = "1.4.0" ) ]
246
250
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
248
252
}
249
253
250
254
/// Converts the `CString` into a `String` if it contains valid Unicode data.
@@ -265,7 +269,7 @@ impl CString {
265
269
/// it is guaranteed to not have any interior nul bytes.
266
270
#[ stable( feature = "cstring_into" , since = "1.7.0" ) ]
267
271
pub fn into_bytes ( self ) -> Vec < u8 > {
268
- let mut vec = self . inner . into_vec ( ) ;
272
+ let mut vec = self . into_inner ( ) . into_vec ( ) ;
269
273
let _nul = vec. pop ( ) ;
270
274
debug_assert_eq ! ( _nul, Some ( 0u8 ) ) ;
271
275
vec
@@ -275,7 +279,7 @@ impl CString {
275
279
/// includes the trailing nul byte.
276
280
#[ stable( feature = "cstring_into" , since = "1.7.0" ) ]
277
281
pub fn into_bytes_with_nul ( self ) -> Vec < u8 > {
278
- self . inner . into_vec ( )
282
+ self . into_inner ( ) . into_vec ( )
279
283
}
280
284
281
285
/// Returns the contents of this `CString` as a slice of bytes.
@@ -293,6 +297,24 @@ impl CString {
293
297
pub fn as_bytes_with_nul ( & self ) -> & [ u8 ] {
294
298
& self . inner
295
299
}
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
+ }
296
318
}
297
319
298
320
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
0 commit comments