From 5aedcb1e916711bfeb65c26b5c6210a3fb5d72bf Mon Sep 17 00:00:00 2001 From: Luqman Aden Date: Tue, 5 Aug 2014 14:38:14 -0700 Subject: [PATCH] librustc: Don't allow return_address intrinsic in functions that don't use an out pointer. --- src/libcore/intrinsics.rs | 7 +++++ src/librustc/middle/trans/callee.rs | 4 ++- src/librustc/middle/trans/intrinsic.rs | 13 +++++--- .../compile-fail/intrinsic-return-address.rs | 31 +++++++++++++++++++ src/test/run-pass/intrinsic-return-address.rs | 2 +- 5 files changed, 51 insertions(+), 6 deletions(-) create mode 100644 src/test/compile-fail/intrinsic-return-address.rs diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs index 002babf7df97..1dd3d6ce9db9 100644 --- a/src/libcore/intrinsics.rs +++ b/src/libcore/intrinsics.rs @@ -310,6 +310,13 @@ extern "rust-intrinsic" { /// ``` pub fn transmute(e: T) -> U; + /// Gives the address for the return value of the enclosing function. + /// + /// Using this instrinsic in a function that does not use an out pointer + /// will trigger a compiler error. + #[cfg(not(stage0))] + pub fn return_address() -> *const u8; + /// Returns `true` if a type requires drop glue. pub fn needs_drop() -> bool; diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 3bea9d644625..dd37f3adab9d 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -765,9 +765,11 @@ pub fn trans_call_inner<'a>( assert!(abi == synabi::RustIntrinsic); assert!(dest.is_some()); + let call_info = call_info.expect("no call info for intrinsic call?"); return intrinsic::trans_intrinsic_call(bcx, node, callee_ty, arg_cleanup_scope, args, - dest.unwrap(), substs); + dest.unwrap(), substs, + call_info); } NamedTupleConstructor(substs, disr) => { assert!(dest.is_some()); diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index 154f2b122ab5..359c8d24f727 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -126,7 +126,7 @@ pub fn check_intrinsics(ccx: &CrateContext) { pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId, callee_ty: ty::t, cleanup_scope: cleanup::CustomScopeIndex, args: callee::CallArgs, dest: expr::Dest, - substs: subst::Substs) -> Result<'a> { + substs: subst::Substs, call_info: NodeInfo) -> Result<'a> { let fcx = bcx.fcx; let ccx = fcx.ccx; @@ -426,9 +426,14 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId, *llargs.get(0), *llargs.get(1)), (_, "return_address") => { - PointerCast(bcx, - bcx.fcx.llretptr.get().unwrap(), - Type::i8p(bcx.ccx())) + if !fcx.caller_expects_out_pointer { + tcx.sess.span_err(call_info.span, + "invalid use of `return_address` intrinsic: function \ + does not use out pointer"); + C_null(Type::i8p(ccx)) + } else { + PointerCast(bcx, llvm::get_param(fcx.llfn, 0), Type::i8p(ccx)) + } } // This requires that atomic intrinsics follow a specific naming pattern: diff --git a/src/test/compile-fail/intrinsic-return-address.rs b/src/test/compile-fail/intrinsic-return-address.rs new file mode 100644 index 000000000000..9c1db4057c6c --- /dev/null +++ b/src/test/compile-fail/intrinsic-return-address.rs @@ -0,0 +1,31 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![allow(warnings)] +#![feature(intrinsics)] + +extern "rust-intrinsic" { + fn return_address() -> *const u8; +} + +unsafe fn f() { + let _ = return_address(); + //~^ ERROR invalid use of `return_address` intrinsic: function does not use out pointer +} + +unsafe fn g() -> int { + let _ = return_address(); + //~^ ERROR invalid use of `return_address` intrinsic: function does not use out pointer + 0 +} + +fn main() {} + + diff --git a/src/test/run-pass/intrinsic-return-address.rs b/src/test/run-pass/intrinsic-return-address.rs index a28a79d306bb..91af669340d6 100644 --- a/src/test/run-pass/intrinsic-return-address.rs +++ b/src/test/run-pass/intrinsic-return-address.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -#![feature(intrinsics)]; +#![feature(intrinsics)] use std::ptr;