Skip to content

Commit 1220e01

Browse files
arielb1Ariel Ben-Yehuda
authored and
Ariel Ben-Yehuda
committed
add a recursion limit for type representation
I could have added a check for explicit recursion, as irregular types tend to cause selection errors, but I am not sufficiently sure that cannot be bypassed. Fixes #22919 Fixes #25639 Fixes #26548
1 parent 867fd0a commit 1220e01

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

src/librustc_trans/trans/context.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,9 @@ pub struct LocalCrateContext<'tcx> {
156156
/// contexts around the same size.
157157
n_llvm_insns: Cell<usize>,
158158

159+
/// Depth of the current type-of computation - used to bail out
160+
type_of_depth: Cell<usize>,
161+
159162
trait_cache: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>,
160163
traits::Vtable<'tcx, ()>>>,
161164
}
@@ -470,6 +473,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
470473
unwind_resume_hooked: Cell::new(false),
471474
intrinsics: RefCell::new(FnvHashMap()),
472475
n_llvm_insns: Cell::new(0),
476+
type_of_depth: Cell::new(0),
473477
trait_cache: RefCell::new(FnvHashMap()),
474478
};
475479

@@ -774,6 +778,17 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
774778
obj))
775779
}
776780

781+
pub fn enter_type_of(&self, ty: Ty<'tcx>) -> TypeOfDepthLock<'b, 'tcx> {
782+
let current_depth = self.local.type_of_depth.get();
783+
debug!("enter_type_of({:?}) at depth {:?}", ty, current_depth);
784+
if current_depth > self.sess().recursion_limit.get() {
785+
self.sess().fatal(
786+
&format!("overflow representing the type `{}`", ty))
787+
}
788+
self.local.type_of_depth.set(current_depth + 1);
789+
TypeOfDepthLock(self.local)
790+
}
791+
777792
pub fn check_overflow(&self) -> bool {
778793
self.shared.check_overflow
779794
}
@@ -790,6 +805,14 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
790805
}
791806
}
792807

808+
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);
809+
810+
impl<'a, 'tcx> Drop for TypeOfDepthLock<'a, 'tcx> {
811+
fn drop(&mut self) {
812+
self.0.type_of_depth.set(self.0.type_of_depth.get() - 1);
813+
}
814+
}
815+
793816
/// Declare any llvm intrinsics that you might need
794817
fn declare_intrinsic(ccx: &CrateContext, key: &str) -> Option<ValueRef> {
795818
macro_rules! ifn {

src/librustc_trans/trans/type_of.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
184184
}
185185

186186
debug!("sizing_type_of {:?}", t);
187+
let _recursion_lock = cx.enter_type_of(t);
188+
187189
let llsizingty = match t.sty {
188190
_ if !type_is_sized(cx.tcx(), t) => {
189191
Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)

src/test/compile-fail/issue-26548.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Copyright 2015 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+
// error-pattern: overflow representing the type `S`
12+
13+
trait Mirror { type It; }
14+
impl<T> Mirror for T { type It = Self; }
15+
struct S(Option<<S as Mirror>::It>);
16+
17+
fn main() {
18+
let _s = S(None);
19+
}

0 commit comments

Comments
 (0)