|
| 1 | +#![deny(unsafe_op_in_unsafe_fn)] |
1 | 2 | use crate::ascii;
|
2 | 3 | use crate::borrow::{Borrow, Cow};
|
3 | 4 | use crate::cmp::Ordering;
|
@@ -510,9 +511,16 @@ impl CString {
|
510 | 511 | /// ```
|
511 | 512 | #[stable(feature = "cstr_memory", since = "1.4.0")]
|
512 | 513 | pub unsafe fn from_raw(ptr: *mut c_char) -> CString {
|
513 |
| - let len = sys::strlen(ptr) + 1; // Including the NUL byte |
514 |
| - let slice = slice::from_raw_parts_mut(ptr, len as usize); |
515 |
| - CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) } |
| 514 | + // SAFETY: This is called with a pointer that was obtained from a call |
| 515 | + // to `CString::into_raw` and the length has not been modified. As such, |
| 516 | + // we know there is a NUL byte (and only one) at the end and that the |
| 517 | + // information about the size of the allocation is correct on Rust's |
| 518 | + // side. |
| 519 | + unsafe { |
| 520 | + let len = sys::strlen(ptr) + 1; // Including the NUL byte |
| 521 | + let slice = slice::from_raw_parts_mut(ptr, len as usize); |
| 522 | + CString { inner: Box::from_raw(slice as *mut [c_char] as *mut [u8]) } |
| 523 | + } |
516 | 524 | }
|
517 | 525 |
|
518 | 526 | /// Consumes the `CString` and transfers ownership of the string to a C caller.
|
@@ -1228,9 +1236,21 @@ impl CStr {
|
1228 | 1236 | /// ```
|
1229 | 1237 | #[stable(feature = "rust1", since = "1.0.0")]
|
1230 | 1238 | pub unsafe fn from_ptr<'a>(ptr: *const c_char) -> &'a CStr {
|
1231 |
| - let len = sys::strlen(ptr); |
1232 |
| - let ptr = ptr as *const u8; |
1233 |
| - CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) |
| 1239 | + // SAFETY: The caller has provided a pointer that points to a valid C |
| 1240 | + // string with a NUL terminator of size less than `isize::MAX`, whose |
| 1241 | + // content remain valid and doesn't change for the lifetime of the |
| 1242 | + // returned `CStr`. |
| 1243 | + // |
| 1244 | + // Thus computing the length is fine (a NUL byte exists), the call to |
| 1245 | + // from_raw_parts is safe because we know the length is at most `isize::MAX`, meaning |
| 1246 | + // the call to `from_bytes_with_nul_unchecked` is correct. |
| 1247 | + // |
| 1248 | + // The cast from c_char to u8 is ok because a c_char is always one byte. |
| 1249 | + unsafe { |
| 1250 | + let len = sys::strlen(ptr); |
| 1251 | + let ptr = ptr as *const u8; |
| 1252 | + CStr::from_bytes_with_nul_unchecked(slice::from_raw_parts(ptr, len as usize + 1)) |
| 1253 | + } |
1234 | 1254 | }
|
1235 | 1255 |
|
1236 | 1256 | /// Creates a C string wrapper from a byte slice.
|
@@ -1299,7 +1319,12 @@ impl CStr {
|
1299 | 1319 | #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
|
1300 | 1320 | #[rustc_const_unstable(feature = "const_cstr_unchecked", issue = "none")]
|
1301 | 1321 | pub const unsafe fn from_bytes_with_nul_unchecked(bytes: &[u8]) -> &CStr {
|
1302 |
| - &*(bytes as *const [u8] as *const CStr) |
| 1322 | + // SAFETY: Casting to CStr is safe because its internal representation |
| 1323 | + // is a [u8] too (safe only inside std). |
| 1324 | + // Dereferencing the obtained pointer is safe because it comes from a |
| 1325 | + // reference. Making a reference is then safe because its lifetime |
| 1326 | + // is bound by the lifetime of the given `bytes`. |
| 1327 | + unsafe { &*(bytes as *const [u8] as *const CStr) } |
1303 | 1328 | }
|
1304 | 1329 |
|
1305 | 1330 | /// Returns the inner pointer to this C string.
|
|
0 commit comments