Improving self-referential structs

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