Improving self-referential structs

True because its strings, I still doubt this is worth dropping into unsafe self references.

2 Likes

Transmute without turbofish is pretty scary, since it could easily be UB. I’m guessing you’re widening a lifetime here? You should covert it into a Box<str> with into_boxed_str() to pin it in the heap, if that’s the case.

1 Like

Uhhhhhhhhhhhh.

Okay, thank goodness at least one other person finds this hair-raising.

Here is UB in tokio_imap:

extern crate tokio_imap;
extern crate tokio_codec;
extern crate bytes;

use std::fmt::Debug;
use tokio_codec::Decoder;
use tokio_imap::proto::{ImapCodec};

// Returns Response<'static>
fn make_bomb() -> impl Debug {
    use bytes::{BytesMut, BufMut};
    let mut buf = BytesMut::with_capacity(1_000_000_000);
    buf.put("* OK [UNSEEN 3] Message 3 is first unseen\r\n");

    let mut decoder = ImapCodec::default();
    let mut result = decoder.decode(&mut buf).unwrap().unwrap();

    println!("{:?}", result.response); // seems legit
    result.response
} // result is freed. uh oh.

fn main() {
    let bomb = make_bomb();
    for _ in 0..10 {
        // make other allocations that zero out memory
        make_bomb();
    }
    println!("{:?}", bomb);
}

Release output:

Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("Message 3 is first unseen") }
Data { status: Ok, code: Some(Unseen(3)), information: Some("\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}\u{0}") }

Edit: created undefined behavior in safe code with public Response<'static> field · Issue #30 · djc/tokio-imap · GitHub

3 Likes

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