diff options
| author | Brandon Sanderson <singingboyo@gmail.com> | 2014-11-05 15:05:01 -0800 |
|---|---|---|
| committer | Brandon Sanderson <singingboyo@gmail.com> | 2014-11-06 10:42:40 -0800 |
| commit | d80a62d84bc9fbc9ae7c8bd300bf5416249b51f7 (patch) | |
| tree | aa89a6df3261fd315f2667f4dc794f38bbbccfd7 | |
| parent | 60a669a1743b845dfa349684ef057bc98ec6d840 (diff) | |
| download | rust-d80a62d84bc9fbc9ae7c8bd300bf5416249b51f7.tar.gz rust-d80a62d84bc9fbc9ae7c8bd300bf5416249b51f7.zip | |
Fix soundness hole in struct with expressions.
Fixes #18567. Struct{x:foo, .. with_expr} did not walk with_expr, which allowed
using moved variables in some cases. The CFG for structs also built up with
with_expr happening before the fields, which is now reversed. (Fields are now
before the with_expr in the CFG)
| -rw-r--r-- | src/librustc/middle/cfg/construct.rs | 4 | ||||
| -rw-r--r-- | src/librustc/middle/expr_use_visitor.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/walk-struct-literal-with.rs | 28 |
3 files changed, 34 insertions, 2 deletions
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index 146891825d6..1419c48609b 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -448,8 +448,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } ast::ExprStruct(_, ref fields, ref base) => { - let base_exit = self.opt_expr(base, pred); - self.straightline(expr, base_exit, fields.iter().map(|f| &*f.expr)) + let field_cfg = self.straightline(expr, pred, fields.iter().map(|f| &*f.expr)); + self.opt_expr(base, field_cfg) } ast::ExprRepeat(ref elem, ref count) => { diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index e8a85b89b58..33a8cf43e72 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -672,6 +672,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,TYPER> { } } + // walk the with expression so that complex expressions + // are properly handled. + self.walk_expr(with_expr); + fn contains_field_named(field: &ty::field, fields: &Vec<ast::Field>) -> bool diff --git a/src/test/compile-fail/walk-struct-literal-with.rs b/src/test/compile-fail/walk-struct-literal-with.rs new file mode 100644 index 00000000000..bb3b310a68f --- /dev/null +++ b/src/test/compile-fail/walk-struct-literal-with.rs @@ -0,0 +1,28 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct Mine{ + test: String, + other_val: int +} + +impl Mine{ + fn make_string_bar(mut self) -> Mine{ + self.test = "Bar".to_string(); + self + } +} + +fn main(){ + let start = Mine{test:"Foo".to_string(), other_val:0}; + let end = Mine{other_val:1, ..start.make_string_bar()}; + println!("{}", start.test); //~ ERROR use of moved value: `start.test` +} + |
