Skip to content

Commit ff1c49f

Browse files
committed
Forbid borrow of static items with unsafe interior
1 parent 69ccd80 commit ff1c49f

File tree

6 files changed

+112
-34
lines changed

6 files changed

+112
-34
lines changed

src/librustc/middle/borrowck/check_loans.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -518,11 +518,11 @@ impl<'a> CheckLoanCtxt<'a> {
518518
expr: &ast::Expr,
519519
cmt: mc::cmt)
520520
-> bool {
521-
match cmt.freely_aliasable() {
521+
match cmt.freely_aliasable(this.tcx()) {
522522
None => {
523523
return true;
524524
}
525-
Some(mc::AliasableStaticMut) => {
525+
Some(mc::AliasableStaticMut(..)) => {
526526
return true;
527527
}
528528
Some(cause) => {

src/librustc/middle/borrowck/gather_loans/mod.rs

Lines changed: 33 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -175,9 +175,9 @@ pub fn gather_loans_in_static_initializer(bccx: &mut BorrowckCtxt, expr: &ast::E
175175
move_data: MoveData::new()
176176
};
177177

178+
// FIXME #13005 This should also walk the
179+
// expression.
178180
match expr.node {
179-
// Just visit the expression if the
180-
// item is taking an address.
181181
ast::ExprAddrOf(..) => {
182182
glcx.visit_expr(expr, ());
183183
}
@@ -686,34 +686,45 @@ impl<'a> GatherLoanCtxt<'a> {
686686
-> Result<(),()> {
687687
//! Implements the A-* rules in doc.rs.
688688
689-
match req_kind {
690-
ty::ImmBorrow => {
689+
match (cmt.freely_aliasable(bccx.tcx), req_kind) {
690+
(None, _) => {
691+
/* Uniquely accessible path -- OK for `&` and `&mut` */
691692
Ok(())
692693
}
693-
694-
ty::UniqueImmBorrow | ty::MutBorrow => {
695-
// Check for those cases where we cannot control
696-
// the aliasing and make sure that we are not
697-
// being asked to.
698-
match cmt.freely_aliasable() {
699-
None => {
700-
Ok(())
694+
(Some(mc::AliasableStatic(safety)), ty::ImmBorrow) => {
695+
// Borrow of an immutable static item:
696+
match safety {
697+
mc::InteriorUnsafe => {
698+
// If the static item contains an Unsafe<T>, it has interior mutability.
699+
// In such cases, we cannot permit it to be borrowed, because the
700+
// static item resides in immutable memory and mutating it would
701+
// cause segfaults.
702+
bccx.tcx.sess.span_err(borrow_span,
703+
format!("borrow of immutable static items with \
704+
unsafe interior is not allowed"));
705+
Err(())
701706
}
702-
Some(mc::AliasableStaticMut) => {
703-
// This is nasty, but we ignore the
704-
// aliasing rules if the data is based in
705-
// a `static mut`, since those are always
706-
// unsafe. At your own peril and all that.
707+
mc::InteriorSafe => {
708+
// Immutable static can be borrowed, no problem.
707709
Ok(())
708710
}
709-
Some(alias_cause) => {
710-
bccx.report_aliasability_violation(
711+
}
712+
}
713+
(Some(mc::AliasableStaticMut(..)), _) => {
714+
// Even touching a static mut is considered unsafe. We assume the
715+
// user knows what they're doing in these cases.
716+
Ok(())
717+
}
718+
(Some(alias_cause), ty::UniqueImmBorrow) |
719+
(Some(alias_cause), ty::MutBorrow) => {
720+
bccx.report_aliasability_violation(
711721
borrow_span,
712722
BorrowViolation(loan_cause),
713723
alias_cause);
714-
Err(())
715-
}
716-
}
724+
Err(())
725+
}
726+
(_, _) => {
727+
Ok(())
717728
}
718729
}
719730
}

src/librustc/middle/borrowck/mod.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -130,9 +130,10 @@ fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
130130
ast::ItemStatic(_, _, ex) => {
131131
gather_loans::gather_loans_in_static_initializer(this, ex);
132132
}
133-
_ => {}
133+
_ => {
134+
visit::walk_item(this, item, ());
135+
}
134136
}
135-
visit::walk_item(this, item, ());
136137
}
137138

138139
fn borrowck_fn(this: &mut BorrowckCtxt,
@@ -733,8 +734,8 @@ impl<'a> BorrowckCtxt<'a> {
733734
span,
734735
format!("{} in an aliasable location", prefix));
735736
}
736-
mc::AliasableStatic |
737-
mc::AliasableStaticMut => {
737+
mc::AliasableStatic(..) |
738+
mc::AliasableStaticMut(..) => {
738739
self.tcx.sess.span_err(
739740
span,
740741
format!("{} in a static location", prefix));

src/librustc/middle/mem_categorization.rs

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1222,12 +1222,17 @@ pub fn field_mutbl(tcx: &ty::ctxt,
12221222
return None;
12231223
}
12241224

1225+
pub enum InteriorSafety {
1226+
InteriorUnsafe,
1227+
InteriorSafe
1228+
}
1229+
12251230
pub enum AliasableReason {
12261231
AliasableManaged,
12271232
AliasableBorrowed,
12281233
AliasableOther,
1229-
AliasableStatic,
1230-
AliasableStaticMut,
1234+
AliasableStatic(InteriorSafety),
1235+
AliasableStaticMut(InteriorSafety),
12311236
}
12321237

12331238
impl cmt_ {
@@ -1257,7 +1262,7 @@ impl cmt_ {
12571262
}
12581263
}
12591264

1260-
pub fn freely_aliasable(&self) -> Option<AliasableReason> {
1265+
pub fn freely_aliasable(&self, ctxt: &ty::ctxt) -> Option<AliasableReason> {
12611266
/*!
12621267
* Returns `Some(_)` if this lvalue represents a freely aliasable
12631268
* pointer type.
@@ -1275,7 +1280,7 @@ impl cmt_ {
12751280
cat_interior(b, _) |
12761281
cat_discr(b, _) => {
12771282
// Aliasability depends on base cmt
1278-
b.freely_aliasable()
1283+
b.freely_aliasable(ctxt)
12791284
}
12801285

12811286
cat_copied_upvar(CopiedUpvar {onceness: ast::Once, ..}) |
@@ -1292,10 +1297,16 @@ impl cmt_ {
12921297
}
12931298

12941299
cat_static_item(..) => {
1300+
let int_safe = if ty::type_interior_is_unsafe(ctxt, self.ty) {
1301+
InteriorUnsafe
1302+
} else {
1303+
InteriorSafe
1304+
};
1305+
12951306
if self.mutbl.is_mutable() {
1296-
Some(AliasableStaticMut)
1307+
Some(AliasableStaticMut(int_safe))
12971308
} else {
1298-
Some(AliasableStatic)
1309+
Some(AliasableStatic(int_safe))
12991310
}
13001311
}
13011312

src/librustc/middle/ty.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1996,6 +1996,10 @@ impl TypeContents {
19961996
!self.intersects(TC::Nonpod)
19971997
}
19981998

1999+
pub fn interior_unsafe(&self) -> bool {
2000+
self.intersects(TC::InteriorUnsafe)
2001+
}
2002+
19992003
pub fn moves_by_default(&self, _: &ctxt) -> bool {
20002004
self.intersects(TC::Moves)
20012005
}
@@ -2092,6 +2096,10 @@ pub fn type_is_freezable(cx: &ctxt, t: ty::t) -> bool {
20922096
type_contents(cx, t).is_freezable(cx)
20932097
}
20942098

2099+
pub fn type_interior_is_unsafe(cx: &ctxt, t: ty::t) -> bool {
2100+
type_contents(cx, t).interior_unsafe()
2101+
}
2102+
20952103
pub fn type_contents(cx: &ctxt, ty: t) -> TypeContents {
20962104
let ty_id = type_id(ty);
20972105

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Verify that it is not possible to take the address of
12+
// static items with usnafe interior.
13+
14+
use std::kinds::marker;
15+
use std::ty::Unsafe;
16+
17+
struct MyUnsafe<T> {
18+
value: Unsafe<T>
19+
}
20+
21+
impl<T> MyUnsafe<T> {
22+
fn forbidden(&self) {}
23+
}
24+
25+
enum UnsafeEnum<T> {
26+
VariantSafe,
27+
VariantUnsafe(Unsafe<T>)
28+
}
29+
30+
static STATIC1: UnsafeEnum<int> = VariantSafe;
31+
32+
static STATIC2: Unsafe<int> = Unsafe{value: 1, marker1: marker::InvariantType};
33+
static STATIC3: MyUnsafe<int> = MyUnsafe{value: STATIC2};
34+
35+
static STATIC4: &'static Unsafe<int> = &'static STATIC2;
36+
//~^ ERROR borrow of immutable static items with unsafe interior is not allowed
37+
38+
39+
fn main() {
40+
let a = &STATIC1;
41+
//~^ ERROR borrow of immutable static items with unsafe interior is not allowed
42+
43+
STATIC3.forbidden()
44+
//~^ ERROR borrow of immutable static items with unsafe interior is not allowed
45+
}
46+
47+

0 commit comments

Comments
 (0)