wowlab_tidy/languages/rust/rules/complexity/
large_stack_array.rs1use ra_ap_syntax::ast;
2
3use super::support;
4use crate::{AstCtx, Example, Violation};
5
6#[rustfmt::skip]
7const EXAMPLES: &[Example] = &[
8 Example {
9 label: "large stack array",
10 code: "fn f() { let _buf: [u8; 8192] = [0u8; 8192]; }",
11 pass: false,
12 },
13 Example {
14 label: "small stack array",
15 code: "fn f() { let _buf = [0u8; 64]; }",
16 pass: true,
17 },
18 Example {
19 label: "large array in test",
20 code: "#[cfg(test)]\nmod tests {\n fn t() { let _buf = [0u8; 8192]; }\n}",
21 pass: true,
22 },
23 Example {
24 label: "u64 element array type",
25 code: "struct S { buf: [u64; 1024] }",
26 pass: false,
27 },
28 Example {
29 label: "boxed element array type",
30 code: "struct S { buf: [Box<u32>; 1024] }",
31 pass: false,
32 },
33 Example {
34 label: "tuple element array type",
35 code: "struct S { buf: [(u64, u32); 1024] }",
36 pass: false,
37 },
38 Example {
39 label: "reference element array type",
40 code: "struct S<'a> { buf: [&'a u8; 1024] }",
41 pass: false,
42 },
43 Example {
44 label: "f64 repeat literal array",
45 code: "fn f() { let _b = [0.0f64; 1024]; }",
46 pass: false,
47 },
48 Example {
49 label: "u64 repeat literal array",
50 code: "fn f() { let _b = [0u64; 1024]; }",
51 pass: false,
52 },
53];
54
55crate::ast_rule!(
56 large_stack_array,
57 "Flag large fixed-size arrays on the stack (>threshold bytes). WASM has limited stack.",
58 "WASM has a fixed 1MB stack by default. Large stack arrays can silently overflow it and crash at runtime.",
59 High,
60 params {
61 threshold: i64 = 4096
62 },
63);
64
65fn check_large_stack_array(ctx: &AstCtx<'_>) -> Vec<Violation> {
66 let max_stack_bytes = ctx
67 .file
68 .config
69 .get_u64("rust_large_stack_array", &PARAMS[0]);
70 let type_arrays = ctx
71 .nodes::<ast::ArrayType>()
72 .filter(|array| !ctx.is_in_test(array))
73 .filter_map(|array| {
74 let size = support::estimate_type_size(&ast::Type::ArrayType(array.clone()))?;
75
76 (size > max_stack_bytes).then(|| {
77 ctx.violation(
78 &array,
79 format!(
80 "large stack array ({size} bytes) — consider Box<[T; N]> or Vec<T> (WASM stack is limited)"
81 ),
82 )
83 })
84 });
85 let repeat_arrays = ctx
86 .nodes::<ast::ArrayExpr>()
87 .filter(|array| !ctx.is_in_test(array) && array.semicolon_token().is_some())
88 .filter_map(|array| {
89 let mut expressions = array.exprs();
90 let element = expressions.next()?;
91 let length = expressions.next()?;
92 let total = support::literal_elem_size(&element)?
93 .saturating_mul(support::parse_int_expr(&length)?);
94
95 (total > max_stack_bytes).then(|| {
96 ctx.violation(
97 &array,
98 format!(
99 "large stack array ({total} bytes) — consider Box<[T; N]> or Vec<T> (WASM stack is limited)"
100 ),
101 )
102 })
103 });
104
105 type_arrays.chain(repeat_arrays).collect()
106}
107
108crate::tidy_ast_test!(check_large_stack_array, {
109 crate::example_tests!(EXAMPLES, check_large_stack_array);
110});