From 5c8816cfc9d8b2a1da80e807c3ccb982063b47fb Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 22 Aug 2017 14:36:49 -0700 Subject: [PATCH 1/5] std: Mark allocation functions as nounwind This commit flags all allocation-related functions in liballoc as "this can't unwind" which should largely resolve the size-related issues found on #42808. The documentation on the trait was updated with such a restriction (they can't panic) as well as some other words about the relative instability about implementing a bullet-proof allocator. Closes #42808 --- src/liballoc/allocator.rs | 23 +++++++++++++++++++ src/liballoc/heap.rs | 10 +++++++++ src/liballoc/lib.rs | 1 + src/librustc_trans/attributes.rs | 2 ++ src/test/codegen/dealloc-no-unwind.rs | 32 +++++++++++++++++++++++++++ 5 files changed, 68 insertions(+) create mode 100644 src/test/codegen/dealloc-no-unwind.rs diff --git a/src/liballoc/allocator.rs b/src/liballoc/allocator.rs index f14f27023249e..5a9cd82b9d119 100644 --- a/src/liballoc/allocator.rs +++ b/src/liballoc/allocator.rs @@ -464,6 +464,29 @@ impl fmt::Display for CannotReallocInPlace { /// * if a layout `k` fits a memory block (denoted by `ptr`) /// currently allocated via an allocator `a`, then it is legal to /// use that layout to deallocate it, i.e. `a.dealloc(ptr, k);`. +/// +/// # Unsafety +/// +/// The `Alloc` trait is an `unsafe` trait for a number of reasons, and +/// implementors must ensure that they adhere to these contracts: +/// +/// * Pointers returned from allocation functions must point to valid memory and +/// retain their validity until at least the instance of `Alloc` is dropped +/// itself. +/// +/// * It's undefined behavior if global allocators unwind. This restriction may +/// be lifted in the future, but currently a panic from any of these +/// functions may lead to memory unsafety. Note that as of the time of this +/// writing allocators *not* intending to be global allocators can still panic +/// in their implementation without violating memory safety. +/// +/// * `Layout` queries and calculations in general must be correct. Callers of +/// this trait are allowed to rely on the contracts defined on each method, +/// and implementors must ensure such contracts remain true. +/// +/// Note that this list may get tweaked over time as clarifications are made in +/// the future. Additionally global allocators may gain unique requirements for +/// how to safely implement one in the future as well. pub unsafe trait Alloc { // (Note: existing allocators have unspecified but well-defined diff --git a/src/liballoc/heap.rs b/src/liballoc/heap.rs index 820f2d958d9a8..b2bd9d7d8fafa 100644 --- a/src/liballoc/heap.rs +++ b/src/liballoc/heap.rs @@ -27,24 +27,32 @@ pub mod __core { extern "Rust" { #[allocator] + #[rustc_allocator_nounwind] fn __rust_alloc(size: usize, align: usize, err: *mut u8) -> *mut u8; #[cold] + #[rustc_allocator_nounwind] fn __rust_oom(err: *const u8) -> !; + #[rustc_allocator_nounwind] fn __rust_dealloc(ptr: *mut u8, size: usize, align: usize); + #[rustc_allocator_nounwind] fn __rust_usable_size(layout: *const u8, min: *mut usize, max: *mut usize); + #[rustc_allocator_nounwind] fn __rust_realloc(ptr: *mut u8, old_size: usize, old_align: usize, new_size: usize, new_align: usize, err: *mut u8) -> *mut u8; + #[rustc_allocator_nounwind] fn __rust_alloc_zeroed(size: usize, align: usize, err: *mut u8) -> *mut u8; + #[rustc_allocator_nounwind] fn __rust_alloc_excess(size: usize, align: usize, excess: *mut usize, err: *mut u8) -> *mut u8; + #[rustc_allocator_nounwind] fn __rust_realloc_excess(ptr: *mut u8, old_size: usize, old_align: usize, @@ -52,11 +60,13 @@ extern "Rust" { new_align: usize, excess: *mut usize, err: *mut u8) -> *mut u8; + #[rustc_allocator_nounwind] fn __rust_grow_in_place(ptr: *mut u8, old_size: usize, old_align: usize, new_size: usize, new_align: usize) -> u8; + #[rustc_allocator_nounwind] fn __rust_shrink_in_place(ptr: *mut u8, old_size: usize, old_align: usize, diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs index 2d41ed648102b..8b0dd4e56c664 100644 --- a/src/liballoc/lib.rs +++ b/src/liballoc/lib.rs @@ -105,6 +105,7 @@ #![feature(pattern)] #![feature(placement_in_syntax)] #![feature(placement_new_protocol)] +#![feature(rustc_attrs)] #![feature(shared)] #![feature(slice_get_slice)] #![feature(slice_patterns)] diff --git a/src/librustc_trans/attributes.rs b/src/librustc_trans/attributes.rs index 8863d4ea5ea8a..b6ca1460a7d0a 100644 --- a/src/librustc_trans/attributes.rs +++ b/src/librustc_trans/attributes.rs @@ -119,6 +119,8 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe llvm::AttributePlace::ReturnValue(), llfn); } else if attr.check_name("unwind") { unwind(llfn, true); + } else if attr.check_name("rustc_allocator_nounwind") { + unwind(llfn, false); } } if !target_features.is_empty() { diff --git a/src/test/codegen/dealloc-no-unwind.rs b/src/test/codegen/dealloc-no-unwind.rs new file mode 100644 index 0000000000000..551b66e103a11 --- /dev/null +++ b/src/test/codegen/dealloc-no-unwind.rs @@ -0,0 +1,32 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// no-system-llvm +// compile-flags: -O + +#![crate_type="lib"] + +struct A; + +impl Drop for A { + fn drop(&mut self) { + extern { fn foo(); } + unsafe { foo(); } + } +} + +#[no_mangle] +pub fn a(a: Box) { + // CHECK-LABEL: define void @a + // CHECK: call void @__rust_dealloc + // CHECK-NEXT: call void @foo + let _a = A; + drop(a); +} From f6dd218d3488fbc7dd150ede4baa64a296a8a8d8 Mon Sep 17 00:00:00 2001 From: Tatsuyuki Ishi Date: Mon, 28 Aug 2017 12:52:02 +0900 Subject: [PATCH 2/5] bootstrap: remove unneeded extern crate The crate itself is internally referenced by serde_derive. --- src/bootstrap/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 55358f2ffcb73..84a9e56b644c8 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -123,7 +123,6 @@ extern crate build_helper; extern crate serde_derive; #[macro_use] extern crate lazy_static; -extern crate serde; extern crate serde_json; extern crate cmake; extern crate filetime; From 44668346e17f5002fdc09514cf53f54b22fc6425 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 28 Aug 2017 18:40:57 -0700 Subject: [PATCH 3/5] rustbuild: Fix dependencies of build-manifest No need to depend on librustc! All we need is libstd Closes #44140 --- src/bootstrap/tool.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index d798e8de3dffa..e759f1a3e6f85 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -198,7 +198,7 @@ tool!( Linkchecker, "src/tools/linkchecker", "linkchecker", Mode::Libstd; CargoTest, "src/tools/cargotest", "cargotest", Mode::Libstd; Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest; - BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Librustc; + BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd; RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd; RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd; ); From 7be7dc8fd55599eb9fa80f3f88fb0b190ae17ff8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Fri, 1 Sep 2017 10:06:50 -0700 Subject: [PATCH 4/5] Bump beta to .2 --- src/bootstrap/channel.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/channel.rs b/src/bootstrap/channel.rs index 9c1ae83d38281..d6ce3eb98ecb7 100644 --- a/src/bootstrap/channel.rs +++ b/src/bootstrap/channel.rs @@ -29,7 +29,7 @@ pub const CFG_RELEASE_NUM: &str = "1.21.0"; // An optional number to put after the label, e.g. '.2' -> '-beta.2' // Be sure to make this starts with a dot to conform to semver pre-release // versions (section 9) -pub const CFG_PRERELEASE_VERSION: &str = ".1"; +pub const CFG_PRERELEASE_VERSION: &str = ".2"; pub struct GitInfo { inner: Option, From 38b513dfd105f11c4efcd5f267caaeb321741d96 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 31 Aug 2017 18:04:36 -0700 Subject: [PATCH 5/5] [beta] Boostrap from released compilers No need to use dev any more! --- src/stage0.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stage0.txt b/src/stage0.txt index b7b4909713a5d..76169f3725d5a 100644 --- a/src/stage0.txt +++ b/src/stage0.txt @@ -12,7 +12,7 @@ # source tarball for a stable release you'll likely see `1.x.0` for rustc and # `0.x.0` for Cargo where they were released on `date`. -date: 2017-08-27 +date: 2017-08-31 rustc: 1.20.0 cargo: 0.21.0 @@ -34,4 +34,4 @@ cargo: 0.21.0 # looking at a beta source tarball and it's uncommented we'll shortly comment it # out. -dev: 1 +#dev: 1