-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
New lint: creation of huge array on the stack #4520
Comments
@Shnatsel your last example fails to compile because
So we should detect large numbers – though how large is too large? Should we take the type into account? |
Stack size is different between systems and there is no way to confidently tell if array will fit without asking the kernel. |
The default stack size in Rust is 2Mb: https://doc.rust-lang.org/std/thread/index.html#stack-size Any dynamic length type larger than u16 will definitely allow stack overflow. In fact, if you're making an array of As for large fixed sizes, that's more of a rookie mistake, this code would crash more or less up front, so I'd err on the side of people knowing what they're doing and set a rather high limit such as 512Kb. And yes, the type needs to be taken into account because the memory limit counts against |
@Shnatsel, that's the default stack size for spawned threads. As the page says, "the stack size of the main thread is not determined by Rust". I think a lint like this would best be made to sum all worst-case stack allocations within a given function/stack frame. It, of course, could not reason about the possible stack growth scenarios of the whole program but at the very least it could trigger on: fn main() {
let data1 = [0; 2000000];
if f() {
let data2 = [0; 2000000];
}
} As indeed it's impossible to know the maximum stack size of the system the program would run on, this would essentially be a lint against stack frames that are simply very large (where how large would be configurable like in some other lints) and not necessarily bound to overflow the stack. |
|
I would like to tackle this one. |
I am not sure about local variable allocation in Rust (I've read LLVM documentation and Rust Reference about local variables, but they left me with the feeling that it's not really specified). Is it ok to just sum up all the array allocations on the worst path that are binded to a variable + temp variable with max size? |
Yeah, me neither. I changed the classification to At first, only the "easy" implementation would be enough. So to just search for array allocations and check the size against a threshold.
I would say that this is a good heuristic. |
Hasn't this been implemented? https://rust-lang.github.io/rust-clippy/master/index.html#large_stack_arrays Or is something still missing? |
@cauebs only the "good first issue" part of this comment was implemented. |
@ebroto Thanks! Missed that. Maybe the labels should be updated to reflect that, then. Or even close and open another issue to make it clearer. |
The following code will segfault on playground due to stack overflow:
The problem is that Rust arrays are created on the stack, but this array is too large to fit on the stack.
What's worse, the naive solution doesn't work either:
This still instantiates the array on the stack and segfaults. The proper solution is this:
This issue is particularly tricky if the array size is dynamic, and does not typically manifest on tests, resulting in unexpected crashes in production. Example:
Here
len
can be set to an arbitrarily large number that would overflow the stack. Only length values of typesu8
,i8
,u16
,i16
are definitely safe. The solution is to use one of them or create the array on the heap as described above.The text was updated successfully, but these errors were encountered: