-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Segfault in safe code caused by a use after drop when using index sugar #30438
Comments
Hm, this shouldn't compile because cc @rust-lang/compiler, perhaps this is a dupe of an existing bug? |
It doesn't actually have to do with the Index sugar: http://is.gd/6sCgIy. It seems like it has to do with copying the lifetime bound from the associated type into the function return type: if you manually substitute in |
@alexcrichton I would've guessed it's similar to #29861. |
triage: P-high |
Why does it not compile on nightly in playpen? |
So this seems like it can be closed? |
Unfortunately it seems like we didn't have nightly builds from 2015-12-15 through 2015-12-18. I can confirm that this was broken in rust nightly-2015-12-14 and is rejected (correctly) by rust nightly-2015-12-19. I'll do a quick bisect just to double check what fixed it. |
Hmm. While writing the test and then "simplifying" it, I actually found a related program that continues to segfault: trait Trait { type Out; fn method(&self) -> &Self::Out; }
struct Test<'a> { s: &'a String }
impl<'a> Trait for Test<'a> {
type Out = Test<'a>;
fn method(&self) -> &Self::Out {
&Test { s: &self.s }
}
}
fn main() {
let s = "Hello World".to_string();
let test = Test { s: &s };
let r = test.method();
println!("{}", test.s); // OK since test is valid
println!("{}", r.s); // Segfault (value ref'd by r dropped during index)
} |
(apparently the switch from explicit |
fn silly<'y, 'a>(s: &'y Test<'a>) -> &'y <Test<'a> as Trait>::Out {
let x = Test { s: &s.s }; &x
} what? |
There's some really funky interactions going on here with associated types and with lifetime bounds on the struct. For example, this version of @arielb1's refined example is (correctly) rejected by the compiler: http://is.gd/NGHvkm but the only different between the two is that in the version that is rejected, we have a maximally parameteric blanket impl: impl<T> Trait for T { type Out = T; } while for the version that is accepted, we have instead a more narrowly focused impl (that happens to be lifetime parameterized): impl<'b> Trait for Test<'b> { type Out = Test<'b>; } |
So far I think that something is funky in the region inference. Looking at the output from ConstrainRegSubVar(ReFree(CodeExtent(7/CallSiteScope { fn_id: 15, body_id: 32 }), BrNamed(DefId { krate: 0, node: DefIndex(11) => silly::'y }, 'y(76))), '_#11r))
Yet despite the above constraint, the region variable is eventually "solved" and resolves as follows: resolve_var('_#11r) = ReScope(CodeExtent(18/Misc(38))) But this does not make sense; the node id 38 is contained within the function that is being called, so that ReScope cannot possibly be long-lived enough to satisfy the above constraint (right?) Update: for some reason, during expansion when we encounter the above quoted ConstrainRegSubVar, it falls into the early check if a relationship is implied by the givens. I'll keep looking; I'd like to know what given is being employed here to deduce that, but such info is not yet included in the BTW, here is the region constraint graph as generated by relevant lines from current
|
@pnkfelix you might want to wrap some of that up in code fences, it's getting reinterpreted as markdown. |
@eddyb yeah I was debating; the lines are really long so that's why I didn't do code fences at first, since I figured it was better to let the lines wrap. I'll manually wrap the lines and add fences. |
Okay I think I found the bug. The actual region-graph representation (as opposed to what the (Presumably the logic here is that all such concrete regions are existentially bound and thus we can abstract them into a single node, in terms of the reasoning that will be employed for the purposes of finding solutions to the constraint sets.)
The problem is that other code in the region_inference module assumes that we aren't playing such games. In particular, the But that depth-first traversal will then see all the edges that are going both into and out of the single dummy-idx node! So it ends up over-expanding the |
…odes. Why do this: The RegionGraph representation previously conflated all of the non-variable regions (i.e. the concrete regions such as lifetime parameters to the current function) into a single dummy node. A single dummy node leads DFS on a graph `'a -> '_#1 -> '_#0 -> 'b` to claim that `'_#1` is reachable from `'_#0` (due to `'a` and `'b` being conflated in the graph representation), which is incorrect (and can lead to soundness bugs later on in compilation, see rust-lang#30438). Splitting the dummy node ensures that DFS will never introduce new ancestor relationships between nodes for variable regions in the graph.
…g-expand-givens-dfs, r=nikomatsakis Split dummy-idx node to fix expand_givens DFS (Much more detail in commit comments.) Fix #30438.
…odes. Why do this: The RegionGraph representation previously conflated all of the non-variable regions (i.e. the concrete regions such as lifetime parameters to the current function) into a single dummy node. A single dummy node leads DFS on a graph `'a -> '_#1 -> '_#0 -> 'b` to claim that `'_#1` is reachable from `'_#0` (due to `'a` and `'b` being conflated in the graph representation), which is incorrect (and can lead to soundness bugs later on in compilation, see rust-lang#30438). Splitting the dummy node ensures that DFS will never introduce new ancestor relationships between nodes for variable regions in the graph.
I've been playing a bit around
std::ops::Index
and the associated sugar.I found a case where it may cause a segfault. I tried to reproduce the issue in a simplified code and got the following one (also available on playpen)
I guess this code should not compile since on the last line,
r
points to a dropped value.The text was updated successfully, but these errors were encountered: