Skip to content

Borrow checker allows slice lifetime to be extended #22779

Closed
@AerialX

Description

@AerialX

It's possible to create a slice from another slice with a lifetime longer than the original without use of the "unsafe" keyword. This allows for accessing memory after the original contents of a slice have been free'd, among other bad things.

trait Tr<'a, T> {
    fn renew<'b: 'a>(self) -> &'b mut [T];
}
impl<'a, T> Tr<'a, T> for &'a mut [T] {
    fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b {
        &mut self[..]
    }
}

See this code for an example.

Activity

edwardw

edwardw commented on Feb 26, 2015

@edwardw
Contributor

If the trait method also has that where clause:

trait Tr<'a, T> {
    fn renew<'b: 'a>(self) -> &'b mut [T] where 'a: 'b;
}
...

then the full example code does report a "*v does not live long enough" error.

pnkfelix

pnkfelix commented on Feb 26, 2015

@pnkfelix
Member

P-backcompat-lang; but probably 1.0 polish. (i.e. not clear that this has to be dealt with by the beta.)

pnkfelix

pnkfelix commented on Feb 26, 2015

@pnkfelix
Member
added this to the 1.0 milestone on Feb 26, 2015
nikomatsakis

nikomatsakis commented on Feb 28, 2015

@nikomatsakis
Contributor

The bug here is that the where clause is accepted in the impl when it is not present in the trait.

nikomatsakis

nikomatsakis commented on Feb 28, 2015

@nikomatsakis
Contributor

I think I know why this is the case. I think @jroesch and I planned to come back and fix this and totally forgot, in particular!

self-assigned this
on Feb 28, 2015
jroesch

jroesch commented on Mar 2, 2015

@jroesch
Member

@nikomatsakis I have a vague memory of us needing to loop back and take care of this. I don't have much free time, but I'm interested and will poke at this, should be simple enough to patch.

jroesch

jroesch commented on Mar 3, 2015

@jroesch
Member

So I looked into this and it seems that the bug is subtle as it only effects bounds that involve constraints where 'a : 'b and 'b : 'a (meaning 'a == 'b).

If we look at a reduced test case with just an added bound it is rejected:

trait T {
    fn foo<'a, 'b, A>(self) -> A;
}

impl T for () {
    fn foo<'a, 'b, A>(self) -> A where 'a : 'b {}
}

fn main() {}

If we go back to a trait of the form above we can see the same kind of soundness bug:

trait T<'a> {
    fn foo<'b : 'a, A>(&'a self) -> A;
}

impl<'a> T<'a> for () {
    fn foo<'b : 'a, A>(&'a self) -> A where 'a : 'b { panic!("bleh") }
}

fn main() {}

Though if we drop the extra bound:

trait T<'a> {
    fn foo<'b, A>(&'a self) -> A;
}

impl<'a> T<'a> for () {
    fn foo<'b, A>(&'a self) -> A where 'a : 'b { panic!("bleh") }
}

fn main() {}
jroesch

jroesch commented on Mar 3, 2015

@jroesch
Member

The error we do trigger when dropping the constraint is here: https://github.com/rust-lang/rust/blob/master/src/librustc_typeck/check/compare_method.rs#L394. This code was slated to be removed once we delete ParamBounds.

@nikomatsakis it isn't clear to me why adding both 'a : 'b and 'b : 'a causes this not to be checked. I played with a couple other extraneous constraints on the implementation and those implementations are all rejected.

edwardw

edwardw commented on Mar 3, 2015

@edwardw
Contributor

@jroesch, I think that we have TraitPredicate excess check built-in in fulfill.rs#L326, but do no such thing for RegionOutlives or TypeOutlives predicates, fulfill.rs#L360 and fulfill.rs#L374 respectively.

jroesch

jroesch commented on Mar 3, 2015

@jroesch
Member

@edwardw so the weird thing about the code above is some excess bounds will cause it to trip and others won't. It probably has to do with early/late bound regions since I'm not sure what else would be causing that to trip.

I see what you are talking about now that I look, and it may be the fact that the predicates are attached to the inference context that is causing this problem. The above chunk of code (related to error 195) needs to be removed anyways so I might just delete it and chase down the ramifications.

10 remaining items

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Relationships

None yet

    Participants

    @alexcrichton@AerialX@nikomatsakis@pnkfelix@edwardw

    Issue actions

      Borrow checker allows slice lifetime to be extended · Issue #22779 · rust-lang/rust