|
| 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