# Panic in \`CString::from\_slice\` and friends

**URL:** <https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580>\
**Category:** libs\
**Created:** [February 12, 2015, 6:20am UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580 "2015-02-12T06:20:29Z")\
**Posts on this page:** 13\
**Page:** 1

<div class="post-metadata">

**Author:** ![aturon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aturon/32/3272_2.png) [@aturon](https://internals.rust-lang.org/u/aturon)\
**Post date:** [February 12, 2015, 6:20am UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/1 "2015-02-12T06:20:29Z")

</div>

When converting from Rust strings to C strings, we have to ensure that there are no _interior nulls_, which cannot be represented in C strings.

Currently, we do this via the `CString` type in [methods like `from_slice`](http://static.rust-lang.org/doc/master/std/ffi/struct.CString.html#method.from_slice), which _panic_ if an interior null is found.

Since interior nulls are relatively rare, that means there are rare panics lurking in anything that winds up calling system APIs, such as IO.

For things like IO, however, we could easily propagate such errors using the [`InvalidInput` variant](http://static.rust-lang.org/doc/master/std/io/enum.ErrorKind.html) for `std::io` errors. That would have essentially zero ergonomic impact on users of IO and similar APIs, but might offer somewhat more graceful handling of the situation.

There are a couple of questions to ask:

- Is there a reasonable way for clients to handle `InvalidInput` errors other than simply panicking themselves? That is, would this change actually benefit code in practice?

- Would the ergonomics of `CString::from_slice` take too much of a hit for code that uses it directly?

cc @mzabaluev@alexcrichton @wycats

---

<div class="post-metadata">

**Author:** ![aturon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aturon/32/3272_2.png) [@aturon](https://internals.rust-lang.org/u/aturon)\
**Post date:** [February 12, 2015, 6:24am UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/2 "2015-02-12T06:24:31Z")

</div>

Thinking a bit more, it’s probably possible to change the behavior within `std` from panicking to producing an error variant in the future (this is broadly considered a backwards-compatible change). So this may just be a question about the right “default” behavior for `CString`.

---

<div class="post-metadata">

**Author:** ![mzabaluev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mzabaluev/32/3082_2.png) [@mzabaluev](https://internals.rust-lang.org/u/mzabaluev)\
**Post date:** [February 12, 2015, 11:03am UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/3 "2015-02-12T11:03:05Z")

</div>

I favor a domain specific error with a `FromError` impl for converting into `std::io::Error`. A `NulError` can provide programmatic access to the position of the first NUL encountered. `CString::from_vec` also needs a move-friendly `Err` value with the original vector.

@aturon, I don’t see how can `CString::from_slice` be changed to return `Result` without breaking backward compatibility?

---

<div class="post-metadata">

**Author:** ![tbu](https://avatars.discourse-cdn.com/v4/letter/t/839c29/32.png) [@tbu](https://internals.rust-lang.org/u/tbu)\
**Post date:** [February 12, 2015, 12:02pm UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/4 "2015-02-12T12:02:17Z")

</div>

Definitely in favor of methods returning a `Result` instead of panicking here!

---

<div class="post-metadata">

**Author:** ![iopq](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/iopq/32/78_2.png) [@iopq](https://internals.rust-lang.org/u/iopq)\
**Post date:** [February 12, 2015, 1:44pm UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/5 "2015-02-12T13:44:33Z")

</div>

Why would it panic? Let me `unwrap()` it when I want it to panic and let me give a sensible default if I don’t.

---

<div class="post-metadata">

**Author:** ![kornel](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/kornel/32/2711_2.png) [@kornel](https://internals.rust-lang.org/u/kornel)\
**Post date:** [February 13, 2015, 1:21am UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/6 "2015-02-13T01:21:30Z")

</div>

Are there cases where one would get `NUL` in a C string, other than data corruption or an attack?

I’ve encountered the problem of internal `NUL`s vs C strings only in PHP filesystem APIs, but there it’s pretty much guaranteed to be an attack attempt — [http://cwe.mitre.org/data/definitions/626.html](http://cwe.mitre.org/data/definitions/626.html)

Even if Rust’s stdlib handled such strings safely and gracefully, my app probably wouldn’t, so to me a `panic!` in such case seems fine.

---

<div class="post-metadata">

**Author:** ![mzabaluev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mzabaluev/32/3082_2.png) [@mzabaluev](https://internals.rust-lang.org/u/mzabaluev)\
**Post date:** [February 13, 2015, 6:16am UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/7 "2015-02-13T06:16:03Z")

</div>

The hazard here is that NUL is so rare in real-world string data that it is easy to get overlooked during development, unless the developers consciously test invalid inputs.

Imagine you’ve got this library interface to work with:

```rust
fn set_text(text: &str) {
    let c_text = CString::from_slice(text); // panic lurks here
    unsafe { ffi::set_text(c_text.as_ptr()) };
}

```

Unless you look at the code, you never know that the input string has some additional constraint, which is never enforced in pure Rust code because it is only imposed by C libraries. The creator of that code might not even have been aware of the problem: the `from_slice` call compiles, and it works with the “normal” strings they tested it with. A `Result` would provide enough of a speed bump to consider the appropriate failure mode, or at least there is an `unwrap()` in the code to indicate the potential panic.

---

<div class="post-metadata">

**Author:** ![winksaville](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/winksaville/32/4321_2.png) [@winksaville](https://internals.rust-lang.org/u/winksaville)\
**Post date:** [February 13, 2015, 5:26pm UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/8 "2015-02-13T17:26:22Z")

</div>

What is the rust idiom for identifying a method may panic? If from\_slice can panic I’d sure like the compiler to know that and tell me.

---

<div class="post-metadata">

**Author:** ![mzabaluev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mzabaluev/32/3082_2.png) [@mzabaluev](https://internals.rust-lang.org/u/mzabaluev)\
**Post date:** [February 13, 2015, 5:34pm UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/9 "2015-02-13T17:34:30Z")

</div>

As I understand the prevailing convention, panics happen only as a result of programmer errors. The way to inform the client about a potential failure when working with external data is is to return a `Result`.

---

<div class="post-metadata">

**Author:** ![winksaville](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/winksaville/32/4321_2.png) [@winksaville](https://internals.rust-lang.org/u/winksaville)\
**Post date:** [February 13, 2015, 7:36pm UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/10 "2015-02-13T19:36:53Z")

</div>

So I just looked at the docs for from\_slice and at least it does say it panics, but based on what mzabaluev@ said I’d say it should return Result.

A search turned up this FAQ [http://doc.rust-lang.org/complement-lang-faq.html#why-is-panic-unwinding-non-recoverable-within-a-task?-why-not-try-to-“catch-exceptions”?](http://doc.rust-lang.org/complement-lang-faq.html#why-is-panic-unwinding-non-recoverable-within-a-task?-why-not-try-to-%22catch-exceptions%22?) entry about panics which says they can only be caught “outside of a task”. Can someone point me to some example code on how “catch” a panic and have the application resume/recover?

---

<div class="post-metadata">

**Author:** ![stebalien](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/stebalien/32/228_2.png) [@stebalien](https://internals.rust-lang.org/u/stebalien)\
**Post date:** [February 13, 2015, 7:46pm UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/11 "2015-02-13T19:46:24Z")

</div>

I’ve actually had to re-implement the null checking part of `from_slice` and then call `from_slice_unchecked` to prevent this panic so I’d really appreciate this change.

---

<div class="post-metadata">

**Author:** ![mzabaluev](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/mzabaluev/32/3082_2.png) [@mzabaluev](https://internals.rust-lang.org/u/mzabaluev)\
**Post date:** [February 14, 2015, 5:26am UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/12 "2015-02-14T05:26:14Z")

</div>

Filed as a RFC PR: [https://github.com/rust-lang/rfcs/pull/840](https://github.com/rust-lang/rfcs/pull/840)

---

<div class="post-metadata">

**Author:** ![aturon](https://sea2.discourse-cdn.com/flex002/user_avatar/internals.rust-lang.org/aturon/32/3272_2.png) [@aturon](https://internals.rust-lang.org/u/aturon)\
**Post date:** [March 25, 2019, 8:23am UTC](https://internals.rust-lang.org/t/panic-in-cstring-from-slice-and-friends/1580/13 "2019-03-25T08:23:54Z")

</div>

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.
