Skip to content

Commit 48975e3

Browse files
committed
Add span_bug for locals larger than 1GB
use ilog2 Update compiler/rustc_codegen_ssa/messages.ftl Co-authored-by: Michael Goulet <michael@errs.io> Run test only on 64 bit
1 parent 588a420 commit 48975e3

File tree

5 files changed

+57
-1
lines changed

5 files changed

+57
-1
lines changed

compiler/rustc_codegen_ssa/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$e
3030
3131
codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
3232
33+
codegen_ssa_dangerous_stack_allocation = dangerous stack allocation of size: {$output} exceeds most system architecture limits
34+
3335
codegen_ssa_dlltool_fail_import_library =
3436
Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
3537
{$stdout}

compiler/rustc_codegen_ssa/src/errors.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,14 @@ pub(crate) struct CheckInstalledVisualStudio;
429429
#[diag(codegen_ssa_insufficient_vs_code_product)]
430430
pub(crate) struct InsufficientVSCodeProduct;
431431

432+
#[derive(Diagnostic)]
433+
#[diag(codegen_ssa_dangerous_stack_allocation)]
434+
pub struct DangerousStackAllocation {
435+
#[primary_span]
436+
pub span: Span,
437+
pub output: String,
438+
}
439+
432440
#[derive(Diagnostic)]
433441
#[diag(codegen_ssa_processing_dymutil_failed)]
434442
#[note]

compiler/rustc_codegen_ssa/src/mir/mod.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ use rustc_middle::{bug, mir, span_bug};
1010
use rustc_target::abi::call::{FnAbi, PassMode};
1111
use tracing::{debug, instrument};
1212

13-
use crate::base;
1413
use crate::traits::*;
14+
use crate::{base, errors};
1515

1616
mod analyze;
1717
mod block;
@@ -29,6 +29,8 @@ use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo};
2929
use self::operand::{OperandRef, OperandValue};
3030
use self::place::PlaceRef;
3131

32+
const MIN_DANGEROUS_SIZE: u64 = 1024 * 1024 * 1024 * 1; // 1 GB
33+
3234
// Used for tracking the state of generated basic blocks.
3335
enum CachedLlbb<T> {
3436
/// Nothing created yet.
@@ -234,6 +236,14 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
234236
let layout = start_bx.layout_of(fx.monomorphize(decl.ty));
235237
assert!(!layout.ty.has_erasable_regions());
236238

239+
if layout.size.bytes() >= MIN_DANGEROUS_SIZE {
240+
let (size_quantity, size_unit) = human_readable_bytes(layout.size.bytes());
241+
cx.tcx().dcx().emit_warn(errors::DangerousStackAllocation {
242+
span: decl.source_info.span,
243+
output: format!("{:.2} {}", size_quantity, size_unit),
244+
});
245+
}
246+
237247
if local == mir::RETURN_PLACE {
238248
match fx.fn_abi.ret.mode {
239249
PassMode::Indirect { .. } => {
@@ -299,6 +309,14 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
299309
}
300310
}
301311

312+
/// Formats a number of bytes into a human readable SI-prefixed size.
313+
/// Returns a tuple of `(quantity, units)`.
314+
pub fn human_readable_bytes(bytes: u64) -> (u64, &'static str) {
315+
static UNITS: [&str; 7] = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"];
316+
let i = ((bytes.checked_ilog2().unwrap_or(0) / 10) as usize).min(UNITS.len() - 1);
317+
(bytes >> (10 * i), UNITS[i])
318+
}
319+
302320
/// Produces, for each argument, a `Value` pointing at the
303321
/// argument's value. As arguments are places, these are always
304322
/// indirect.
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// This test checks that allocating a stack size of 1GB or more results in a warning
2+
//@build-pass
3+
//@ only-64bit
4+
5+
fn func() {
6+
const CAP: usize = std::u32::MAX as usize;
7+
let mut x: [u8; CAP>>1] = [0; CAP>>1];
8+
//~^ warning: dangerous stack allocation of size: 1 GiB exceeds most system architecture limits
9+
x[2] = 123;
10+
println!("{}", x[2]);
11+
}
12+
13+
fn main() {
14+
std::thread::Builder::new()
15+
.stack_size(3 * 1024 * 1024 * 1024)
16+
.spawn(func)
17+
.unwrap()
18+
.join()
19+
.unwrap();
20+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
warning: dangerous stack allocation of size: 1 GiB exceeds most system architecture limits
2+
--> $DIR/large-stack-size-issue-83060.rs:7:9
3+
|
4+
LL | let mut x: [u8; CAP>>1] = [0; CAP>>1];
5+
| ^^^^^
6+
7+
warning: 1 warning emitted
8+

0 commit comments

Comments
 (0)