@@ -94,19 +94,45 @@ const NUL: u8 = 0;
94
94
95
95
/// Scans a C string as a byte slice.
96
96
///
97
- /// The second parameter provides the lifetime for the returned slice;
98
- /// its value is ignored.
99
97
/// The returned slice does not include the terminating NUL byte.
100
98
///
101
99
/// # Panics
102
100
///
103
101
/// Panics if the string pointer is null.
104
- pub unsafe fn parse_as_bytes < ' a , T : ?Sized > ( raw : * const libc:: c_char ,
105
- life_anchor : & ' a T )
106
- -> & ' a [ u8 ]
102
+ ///
103
+ /// # Caveat
104
+ ///
105
+ /// The lifetime of the returned reference is inferred from its usage.
106
+ /// This may be incorrect in many cases. Consider this example:
107
+ ///
108
+ /// ```rust
109
+ /// #[macro_use]
110
+ /// extern crate c_string;
111
+ ///
112
+ /// extern crate libc;
113
+ /// extern "C" {
114
+ /// fn strdup(source: *const libc::c_char) -> *mut libc::c_char;
115
+ /// }
116
+ ///
117
+ /// fn main() {
118
+ /// let ptr = unsafe { strdup(c_str!("Hello!").as_ptr()) };
119
+ /// let s = unsafe { c_string::parse_as_bytes(ptr) };
120
+ ///
121
+ /// unsafe { libc::free(ptr as *mut libc::c_void) };
122
+ ///
123
+ /// // The line below, if uncommented, will access freed memory:
124
+ /// //let guess_what = s[0];
125
+ /// }
126
+ /// ```
127
+ ///
128
+ /// To prevent accidental misuse, the lifetime should be assigned in some
129
+ /// controllable way. This can be a helper function or method taking the
130
+ /// lifetime from a `host` value, when available. In other cases, explicit
131
+ /// annotation may be used.
132
+ pub unsafe fn parse_as_bytes < ' a > ( raw : * const libc:: c_char ) -> & ' a [ u8 ]
107
133
{
108
134
assert ! ( !raw. is_null( ) ) ;
109
- from_raw_ptr ( raw, life_anchor ) . parse_as_bytes ( )
135
+ from_raw_ptr ( raw) . parse_as_bytes ( )
110
136
}
111
137
112
138
/// Scans a C string as UTF-8 string slice.
@@ -122,12 +148,17 @@ pub unsafe fn parse_as_bytes<'a, T: ?Sized>(raw: *const libc::c_char,
122
148
/// # Panics
123
149
///
124
150
/// Panics if the string pointer is null.
151
+ ///
152
+ /// # Caveat
153
+ ///
154
+ /// The lifetime of the returned reference is inferred from its usage.
155
+ /// See the documentation on `parse_as_bytes` for possible pitfalls and
156
+ /// suggested practices to avoid them.
125
157
#[ inline]
126
- pub unsafe fn parse_as_utf8 < ' a , T : ?Sized > ( raw : * const libc:: c_char ,
127
- life_anchor : & ' a T )
128
- -> Result < & ' a str , str:: Utf8Error >
158
+ pub unsafe fn parse_as_utf8 < ' a > ( raw : * const libc:: c_char )
159
+ -> Result < & ' a str , str:: Utf8Error >
129
160
{
130
- str:: from_utf8 ( parse_as_bytes ( raw, life_anchor ) )
161
+ str:: from_utf8 ( parse_as_bytes ( raw) )
131
162
}
132
163
133
164
/// Representation of an allocated C String.
@@ -151,7 +182,7 @@ impl Deref for OwnedCString {
151
182
type Target = CStr ;
152
183
153
184
fn deref ( & self ) -> & CStr {
154
- unsafe { from_ptr_internal ( self . ptr , self ) }
185
+ unsafe { from_ptr_internal ( self . ptr ) }
155
186
}
156
187
}
157
188
@@ -476,11 +507,10 @@ impl fmt::Debug for CStrBuf {
476
507
}
477
508
}
478
509
479
- unsafe fn from_ptr_internal < ' a , T : ?Sized > ( ptr : * const libc:: c_char ,
480
- life_anchor : & ' a T )
481
- -> & ' a CStr
510
+ #[ inline]
511
+ unsafe fn from_ptr_internal < ' a > ( ptr : * const libc:: c_char ) -> & ' a CStr
482
512
{
483
- mem:: copy_lifetime ( life_anchor , & * ( ptr as * const CStr ) )
513
+ mem:: transmute ( & * ( ptr as * const CStr ) )
484
514
}
485
515
486
516
/// Create a `CStr` reference out of a static byte array.
@@ -497,7 +527,7 @@ pub fn from_static_bytes(bytes: &'static [u8]) -> &'static CStr {
497
527
"static byte string is not null-terminated: \" {}\" " ,
498
528
escape_bytestring( bytes) ) ;
499
529
let ptr = bytes. as_ptr ( ) as * const libc:: c_char ;
500
- unsafe { from_ptr_internal ( ptr, bytes ) }
530
+ unsafe { from_ptr_internal ( ptr) }
501
531
}
502
532
503
533
/// Create a `CStr` reference out of a static string.
@@ -513,7 +543,7 @@ pub fn from_static_str(s: &'static str) -> &'static CStr {
513
543
assert ! ( s. ends_with( "\0 " ) ,
514
544
"static string is not null-terminated: \" {}\" " , s) ;
515
545
let ptr = s. as_ptr ( ) as * const libc:: c_char ;
516
- unsafe { from_ptr_internal ( ptr, s ) }
546
+ unsafe { from_ptr_internal ( ptr) }
517
547
}
518
548
519
549
/// Constructs a `CStr` reference from a raw pointer to a
@@ -525,12 +555,17 @@ pub fn from_static_str(s: &'static str) -> &'static CStr {
525
555
/// # Panics
526
556
///
527
557
/// Panics if the pointer is null.
528
- pub unsafe fn from_raw_ptr < ' a , T : ?Sized > ( ptr : * const libc:: c_char ,
529
- life_anchor : & ' a T )
530
- -> & ' a CStr
558
+ ///
559
+ /// # Caveat
560
+ ///
561
+ /// The lifetime of the returned reference is inferred from its usage.
562
+ /// See the documentation on `parse_as_bytes` for possible pitfalls and
563
+ /// suggested practices to avoid them.
564
+ #[ inline]
565
+ pub unsafe fn from_raw_ptr < ' a > ( ptr : * const libc:: c_char ) -> & ' a CStr
531
566
{
532
567
assert ! ( !ptr. is_null( ) ) ;
533
- from_ptr_internal ( ptr, life_anchor )
568
+ from_ptr_internal ( ptr)
534
569
}
535
570
536
571
impl CStr {
@@ -593,7 +628,7 @@ impl Deref for CStrBuf {
593
628
CStrData :: Owned ( ref v) => ( * v) . as_ptr ( ) ,
594
629
CStrData :: InPlace ( ref a) => a. as_ptr ( )
595
630
} as * const libc:: c_char ;
596
- unsafe { from_ptr_internal ( p, self ) }
631
+ unsafe { from_ptr_internal ( p) }
597
632
}
598
633
}
599
634
@@ -648,7 +683,7 @@ pub unsafe fn parse_c_multistring<F>(buf: *const libc::c_char,
648
683
None => ( false , 0 )
649
684
} ;
650
685
while ( !limited_count || ctr < limit) && * curr_ptr != 0 {
651
- let bytes = parse_as_bytes ( curr_ptr, & buf ) ;
686
+ let bytes = parse_as_bytes ( curr_ptr) ;
652
687
f ( bytes) ;
653
688
curr_ptr = curr_ptr. offset ( bytes. len ( ) as isize + 1 ) ;
654
689
ctr += 1 ;
0 commit comments