Skip to main content

wowlab_tidy/languages/rust/rules/complexity/
large_stack_array.rs

1use 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});