Skip to content

Commit 90a3f14

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 ead4a8f commit 90a3f14

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
@@ -32,6 +32,8 @@ codegen_ssa_copy_path_buf = unable to copy {$source_file} to {$output_path}: {$e
3232
3333
codegen_ssa_create_temp_dir = couldn't create a temp dir: {$error}
3434
35+
codegen_ssa_dangerous_stack_allocation = dangerous stack allocation of size: {$output} exceeds most system architecture limits
36+
3537
codegen_ssa_dlltool_fail_import_library =
3638
Dlltool could not create import library with {$dlltool_path} {$dlltool_args}:
3739
{$stdout}

compiler/rustc_codegen_ssa/src/errors.rs

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

494+
#[derive(Diagnostic)]
495+
#[diag(codegen_ssa_dangerous_stack_allocation)]
496+
pub struct DangerousStackAllocation {
497+
#[primary_span]
498+
pub span: Span,
499+
pub output: String,
500+
}
501+
494502
#[derive(Diagnostic)]
495503
#[diag(codegen_ssa_processing_dymutil_failed)]
496504
#[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::callconv::{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;
@@ -30,6 +30,8 @@ use self::debuginfo::{FunctionDebugContext, PerLocalVarDebugInfo};
3030
use self::operand::{OperandRef, OperandValue};
3131
use self::place::PlaceRef;
3232

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

250+
if layout.size.bytes() >= MIN_DANGEROUS_SIZE {
251+
let (size_quantity, size_unit) = human_readable_bytes(layout.size.bytes());
252+
cx.tcx().dcx().emit_warn(errors::DangerousStackAllocation {
253+
span: decl.source_info.span,
254+
output: format!("{:.2} {}", size_quantity, size_unit),
255+
});
256+
}
257+
248258
if local == mir::RETURN_PLACE {
249259
match fx.fn_abi.ret.mode {
250260
PassMode::Indirect { .. } => {
@@ -310,6 +320,14 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
310320
}
311321
}
312322

323+
/// Formats a number of bytes into a human readable SI-prefixed size.
324+
/// Returns a tuple of `(quantity, units)`.
325+
pub fn human_readable_bytes(bytes: u64) -> (u64, &'static str) {
326+
static UNITS: [&str; 7] = ["B", "KiB", "MiB", "GiB", "TiB", "PiB", "EiB"];
327+
let i = ((bytes.checked_ilog2().unwrap_or(0) / 10) as usize).min(UNITS.len() - 1);
328+
(bytes >> (10 * i), UNITS[i])
329+
}
330+
313331
/// Produces, for each argument, a `Value` pointing at the
314332
/// argument's value. As arguments are places, these are always
315333
/// 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)