Rollup merge of #72963 - poliorcetics:cstring-from-raw, r=dtolnay

Cstring `from_raw` and `into_raw` safety precisions

Fixes #48525.
Fixes #68456.

This issue had two points:

- The one about `from_raw` has been addressed (I hope).
- The other one, about `into_raw`, has only been partially fixed.

About `into_raw`: the idea was to:

> steer users away from using the pattern of CString::{into_raw,from_raw} when interfacing with C APIs that may change the effective length of the string by writing interior NULs or erasing the final NUL

I tried making a `Vec<c_char>` like suggested but my current solution feels very unsafe and *hacky* to me (most notably the type cast), I included it here to make it available for discussion:

```rust
fn main() {
    use std::os::raw::c_char;

    let v = String::from("abc")
        .bytes()
        // From u8 to i8,
        // I feel like it will be a problem for values of u8 > 255
        .map(|c| c as c_char)
        .collect::<Vec<_>>();

    dbg!(v);
}
```
This commit is contained in:
Ralf Jung 2020-06-08 09:55:30 +02:00 committed by GitHub
commit 824ea6bf2d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -395,6 +395,12 @@ impl CString {
/// ownership of a string that was allocated by foreign code) is likely to lead
/// to undefined behavior or allocator corruption.
///
/// It should be noted that the length isn't just "recomputed," but that
/// the recomputed length must match the original length from the
/// [`into_raw`] call. This means the [`into_raw`]/`from_raw` methods
/// should not be used when passing the string to C functions that can
/// modify the string's length.
///
/// > **Note:** If you need to borrow a string that was allocated by
/// > foreign code, use [`CStr`]. If you need to take ownership of
/// > a string that was allocated by foreign code, you will need to
@ -440,6 +446,11 @@ impl CString {
///
/// Failure to call [`from_raw`] will lead to a memory leak.
///
/// The C side must **not** modify the length of the string (by writing a
/// `NULL` somewhere inside the string or removing the final one) before
/// it makes it back into Rust using [`from_raw`]. See the safety section
/// in [`from_raw`].
///
/// [`from_raw`]: #method.from_raw
///
/// # Examples