Limit recursion depth for macro expansions, closes #17628
This commit is contained in:
parent
60e7317345
commit
49e976d771
4 changed files with 35 additions and 0 deletions
|
@ -291,6 +291,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
|
||||||
crate_name: crate_name.to_string(),
|
crate_name: crate_name.to_string(),
|
||||||
deriving_hash_type_parameter: sess.features.borrow().default_type_params,
|
deriving_hash_type_parameter: sess.features.borrow().default_type_params,
|
||||||
enable_quotes: sess.features.borrow().quote,
|
enable_quotes: sess.features.borrow().quote,
|
||||||
|
recursion_limit: sess.recursion_limit.get(),
|
||||||
};
|
};
|
||||||
let ret = syntax::ext::expand::expand_crate(&sess.parse_sess,
|
let ret = syntax::ext::expand::expand_crate(&sess.parse_sess,
|
||||||
cfg,
|
cfg,
|
||||||
|
|
|
@ -463,6 +463,7 @@ pub struct ExtCtxt<'a> {
|
||||||
pub exported_macros: Vec<P<ast::Item>>,
|
pub exported_macros: Vec<P<ast::Item>>,
|
||||||
|
|
||||||
pub syntax_env: SyntaxEnv,
|
pub syntax_env: SyntaxEnv,
|
||||||
|
pub recursion_count: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ExtCtxt<'a> {
|
impl<'a> ExtCtxt<'a> {
|
||||||
|
@ -478,6 +479,7 @@ impl<'a> ExtCtxt<'a> {
|
||||||
trace_mac: false,
|
trace_mac: false,
|
||||||
exported_macros: Vec::new(),
|
exported_macros: Vec::new(),
|
||||||
syntax_env: env,
|
syntax_env: env,
|
||||||
|
recursion_count: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -552,6 +554,13 @@ impl<'a> ExtCtxt<'a> {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
pub fn bt_push(&mut self, ei: ExpnInfo) {
|
pub fn bt_push(&mut self, ei: ExpnInfo) {
|
||||||
|
self.recursion_count += 1;
|
||||||
|
if self.recursion_count > self.ecfg.recursion_limit {
|
||||||
|
self.span_fatal(ei.call_site,
|
||||||
|
format!("Recursion limit reached while expanding the macro `{}`",
|
||||||
|
ei.callee.name).as_slice());
|
||||||
|
}
|
||||||
|
|
||||||
let mut call_site = ei.call_site;
|
let mut call_site = ei.call_site;
|
||||||
call_site.expn_id = self.backtrace;
|
call_site.expn_id = self.backtrace;
|
||||||
self.backtrace = self.codemap().record_expansion(ExpnInfo {
|
self.backtrace = self.codemap().record_expansion(ExpnInfo {
|
||||||
|
@ -563,6 +572,7 @@ impl<'a> ExtCtxt<'a> {
|
||||||
match self.backtrace {
|
match self.backtrace {
|
||||||
NO_EXPANSION => self.bug("tried to pop without a push"),
|
NO_EXPANSION => self.bug("tried to pop without a push"),
|
||||||
expn_id => {
|
expn_id => {
|
||||||
|
self.recursion_count -= 1;
|
||||||
self.backtrace = self.codemap().with_expn_info(expn_id, |expn_info| {
|
self.backtrace = self.codemap().with_expn_info(expn_id, |expn_info| {
|
||||||
expn_info.map_or(NO_EXPANSION, |ei| ei.call_site.expn_id)
|
expn_info.map_or(NO_EXPANSION, |ei| ei.call_site.expn_id)
|
||||||
});
|
});
|
||||||
|
|
|
@ -1069,6 +1069,7 @@ pub struct ExpansionConfig {
|
||||||
pub crate_name: String,
|
pub crate_name: String,
|
||||||
pub deriving_hash_type_parameter: bool,
|
pub deriving_hash_type_parameter: bool,
|
||||||
pub enable_quotes: bool,
|
pub enable_quotes: bool,
|
||||||
|
pub recursion_limit: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ExpansionConfig {
|
impl ExpansionConfig {
|
||||||
|
@ -1077,6 +1078,7 @@ impl ExpansionConfig {
|
||||||
crate_name: crate_name,
|
crate_name: crate_name,
|
||||||
deriving_hash_type_parameter: false,
|
deriving_hash_type_parameter: false,
|
||||||
enable_quotes: false,
|
enable_quotes: false,
|
||||||
|
recursion_limit: 64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
src/test/compile-fail/infinite-macro-expansion.rs
Normal file
22
src/test/compile-fail/infinite-macro-expansion.rs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#![feature(macro_rules)]
|
||||||
|
|
||||||
|
macro_rules! recursive(
|
||||||
|
() => (
|
||||||
|
recursive!() //~ ERROR Recursion limit reached while expanding the macro `recursive`
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
recursive!()
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue