Skip to content

Rust compiles invalid program which segfaults - borrowed pointer to trait object outlives original value #11374

@netvl

Description

@netvl

Here is a very simple program which employs trait objects:

c.rc:

#[crate_id = "c#0.1"];
#[crate_type = "bin"];

mod m1;
mod m2;

m1.rs:

use std::io;

pub struct Container<'a> {
    priv reader: &'a mut Reader
}

impl<'a> Container<'a> {
    pub fn wrap<'s>(reader: &'s mut Reader) -> Container<'s> {
        Container { reader: reader }
    }

    pub fn read_to(&self, vec: &mut [u8]) {
        self.reader.read(vec);
    }
}

pub fn for_stdin<'a>() -> Container<'a> {
    let mut r = io::stdin();
    Container::wrap(&mut r as &mut Reader)
}

m2.rs:

use std::vec;

use m1;

#[main]
fn main() {
    let c = m1::for_stdin();
    let mut v = vec::from_elem(10, 0u8);
    c.read_to(v.as_mut_slice());
}

When this program is compiled and run, it fails with segmentation fault:

% rustc c.rc
% ./c
zsh: segmentation fault (core dumped)  ./c

This program is not correct. You can see that m1::for_stdin() function produces a Container<'a, ...> for arbitrary lifetime 'a, but the local variable r is valid only for for_stdin() body. A pointer to r, however, is saved to the Container, and when it is accessed inside m2::main(), a segmentation fault occurs. However, Rust still compiles it. I thought that borrowing checker should prevent this kind of errors.

BTW, I can write &mut r or &mut r as &mut Reader and it will compile either way, but I thought that when going from plain pointers to trait objects I should always specify exact kind of trait object. Not sure that I'm right here thought.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-type-systemArea: Type systemE-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions