Skip to content

Commit 806bc2d

Browse files
committed
Add span_bug for locals larger than 1GB
1 parent 9480767 commit 806bc2d

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

compiler/rustc_codegen_ssa/src/mir/mod.rs

+24
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo};
2727
use self::operand::{OperandRef, OperandValue};
2828
use self::place::PlaceRef;
2929

30+
const MIN_DANGEROUS_SIZE: u64 = 1024 * 1024 * 1024 * 1; // 1 GB
31+
3032
// Used for tracking the state of generated basic blocks.
3133
enum CachedLlbb<T> {
3234
/// Nothing created yet.
@@ -226,6 +228,16 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
226228
let layout = start_bx.layout_of(fx.monomorphize(decl.ty));
227229
assert!(!layout.ty.has_erasable_regions());
228230

231+
if layout.size.bytes() >= MIN_DANGEROUS_SIZE {
232+
let size_str = || {
233+
let (size_quantity, size_unit) = human_readable_bytes(layout.size.bytes());
234+
format!("{:.2} {}", size_quantity, size_unit)
235+
};
236+
span_bug!(decl.source_info.span, "Dangerous stack allocation, size: {:?} of local: {:?} exceeds typical limits on most architectures",
237+
size_str(), local);
238+
239+
}
240+
229241
if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() {
230242
debug!("alloc: {:?} (return place) -> place", local);
231243
let llretptr = start_bx.get_param(0);
@@ -266,6 +278,18 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
266278
}
267279
}
268280

281+
/// Formats a number of bytes into a human readable SI-prefixed size.
282+
/// Returns a tuple of `(quantity, units)`.
283+
//
284+
// Taken from Cargo:
285+
// https://github.com/rust-lang/cargo/blob/2ce45605d9db521b5fd6c1211ce8de6055fdb24e/src/cargo/util/mod.rs#L88-L95
286+
pub fn human_readable_bytes(bytes: u64) -> (f32, &'static str) {
287+
static UNITS: [&str; 7] = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"];
288+
let bytes = bytes as f32;
289+
let i = ((bytes.log2() / 10.0) as usize).min(UNITS.len() - 1);
290+
(bytes / 1024_f32.powi(i as i32), UNITS[i])
291+
}
292+
269293
/// Produces, for each argument, a `Value` pointing at the
270294
/// argument's value. As arguments are places, these are always
271295
/// indirect.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// build-fail
2+
3+
fn func() {
4+
const CAP: usize = std::u32::MAX as usize;
5+
let mut x: [u8; CAP>>1] = [0; CAP>>1];
6+
x[2] = 123;
7+
println!("{}", x[2]);
8+
}
9+
10+
11+
12+
fn main() {
13+
std::thread::Builder::new()
14+
.stack_size(5 * 1024 * 1024 * 1024)
15+
.spawn(func)
16+
.unwrap()
17+
.join()
18+
.unwrap();
19+
}
20+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
WARN rustc_codegen_ssa::mir Dangerous stack allocation, size: "2.00 GiB" of local: _1 exceeds typical limits on most architectures

0 commit comments

Comments
 (0)