Skip to content

Commit

Permalink
Rollup merge of rust-lang#67272 - fisherdarling:master, r=varkor,hell…
Browse files Browse the repository at this point in the history
…ow554

recursion_limit parsing handles overflows

This PR adds overflow handling to `#![recursion_limit]` attribute parsing. If parsing the given value results in an `IntErrorKind::Overflow`, then the recursion_limit is set to `usize::max_value()`.

closes rust-lang#67265
  • Loading branch information
Dylan-DPC authored Feb 17, 2020
2 parents 75b98fb + c53693d commit 3747a48
Show file tree
Hide file tree
Showing 10 changed files with 112 additions and 6 deletions.
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
#![feature(hash_raw_entry)]
#![feature(int_error_matching)]
#![recursion_limit = "512"]

#[macro_use]
Expand Down
46 changes: 40 additions & 6 deletions src/librustc/middle/recursion_limit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,60 @@
// just peeks and looks for that attribute.

use crate::session::Session;
use core::num::IntErrorKind;
use rustc::bug;
use rustc_span::symbol::{sym, Symbol};
use syntax::ast;

use rustc_data_structures::sync::Once;

pub fn update_limits(sess: &Session, krate: &ast::Crate) {
update_limit(krate, &sess.recursion_limit, sym::recursion_limit, 128);
update_limit(krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
update_limit(sess, krate, &sess.recursion_limit, sym::recursion_limit, 128);
update_limit(sess, krate, &sess.type_length_limit, sym::type_length_limit, 1048576);
}

fn update_limit(krate: &ast::Crate, limit: &Once<usize>, name: Symbol, default: usize) {
fn update_limit(
sess: &Session,
krate: &ast::Crate,
limit: &Once<usize>,
name: Symbol,
default: usize,
) {
for attr in &krate.attrs {
if !attr.check_name(name) {
continue;
}

if let Some(s) = attr.value_str() {
if let Some(n) = s.as_str().parse().ok() {
limit.set(n);
return;
match s.as_str().parse() {
Ok(n) => {
limit.set(n);
return;
}
Err(e) => {
let mut err = sess.struct_span_err(
attr.span,
"`recursion_limit` must be a non-negative integer",
);

let value_span = attr
.meta()
.and_then(|meta| meta.name_value_literal().cloned())
.map(|lit| lit.span)
.unwrap_or(attr.span);

let error_str = match e.kind() {
IntErrorKind::Overflow => "`recursion_limit` is too large",
IntErrorKind::Empty => "`recursion_limit` must be a non-negative integer",
IntErrorKind::InvalidDigit => "not a valid integer",
IntErrorKind::Underflow => bug!("`recursion_limit` should never underflow"),
IntErrorKind::Zero => bug!("zero is a valid `recursion_limit`"),
kind => bug!("unimplemented IntErrorKind variant: {:?}", kind),
};

err.span_label(value_span, error_str);
err.emit();
}
}
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/test/ui/recursion_limit/empty.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Test the parse error for an empty recursion_limit

#![recursion_limit = ""] //~ ERROR `recursion_limit` must be a non-negative integer
//~| `recursion_limit` must be a non-negative integer

fn main() {}
10 changes: 10 additions & 0 deletions src/test/ui/recursion_limit/empty.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: `recursion_limit` must be a non-negative integer
--> $DIR/empty.rs:3:1
|
LL | #![recursion_limit = ""]
| ^^^^^^^^^^^^^^^^^^^^^--^
| |
| `recursion_limit` must be a non-negative integer

error: aborting due to previous error

6 changes: 6 additions & 0 deletions src/test/ui/recursion_limit/invalid_digit.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Test the parse error for an invalid digit in recursion_limit

#![recursion_limit = "-100"] //~ ERROR `recursion_limit` must be a non-negative integer
//~| not a valid integer

fn main() {}
10 changes: 10 additions & 0 deletions src/test/ui/recursion_limit/invalid_digit.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: `recursion_limit` must be a non-negative integer
--> $DIR/invalid_digit.rs:3:1
|
LL | #![recursion_limit = "-100"]
| ^^^^^^^^^^^^^^^^^^^^^------^
| |
| not a valid integer

error: aborting due to previous error

7 changes: 7 additions & 0 deletions src/test/ui/recursion_limit/overflow.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// Test the parse error for an overflowing recursion_limit

#![recursion_limit = "999999999999999999999999"]
//~^ ERROR `recursion_limit` must be a non-negative integer
//~| `recursion_limit` is too large

fn main() {}
10 changes: 10 additions & 0 deletions src/test/ui/recursion_limit/overflow.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: `recursion_limit` must be a non-negative integer
--> $DIR/overflow.rs:3:1
|
LL | #![recursion_limit = "999999999999999999999999"]
| ^^^^^^^^^^^^^^^^^^^^^--------------------------^
| |
| `recursion_limit` is too large

error: aborting due to previous error

12 changes: 12 additions & 0 deletions src/test/ui/recursion_limit/zero.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// Test that a `recursion_limit` of 0 is valid

#![recursion_limit = "0"]

macro_rules! test {
() => {};
($tt:tt) => { test!(); };
}

test!(test); //~ ERROR 10:1: 10:13: recursion limit reached while expanding `test!`

fn main() {}
10 changes: 10 additions & 0 deletions src/test/ui/recursion_limit/zero.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
error: recursion limit reached while expanding `test!`
--> $DIR/zero.rs:10:1
|
LL | test!(test);
| ^^^^^^^^^^^^
|
= help: consider adding a `#![recursion_limit="0"]` attribute to your crate (`zero`)

error: aborting due to previous error

0 comments on commit 3747a48

Please sign in to comment.