-
Notifications
You must be signed in to change notification settings - Fork 13.3k
large stack arrays cause segfaults in safe code (even with ulimit unlimited) #34877
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
Comments
On 64-bit Windows I compiled the program as provided using |
(See also #16012.) |
Sorry, did a quick write up on Saturday. I'm running Linux:
with 8GB of memory. So I just receive a segfault; several people on IRC reported the same (one user was on Ubuntu iirc). No warning about main overflowing stack, just a regular segfault. |
@retep998 so on Linux the stack size for userland programs is configurable as an environment variable; Briefly googling, looks like the windows per thread stack is 1MB? https://msdn.microsoft.com/en-us/library/windows/desktop/ms686774(v=vs.85).aspx If the above is true, I'm not sure how the program is correctly running for you? Since it should have tried to allocate a 1GB multi-dim array on the stack. |
@m4b On Windows all functions that use over a page of stack have a stack probe at the beginning. Rust currently doesn't emit stack probes on any other platform, only Windows. This means that if you allocate a giant array on the stack, on platforms other than Windows you can very easily touch a page beyond the guard page of the stack and cause a segfault. On Windows the stack probe will first probe all the space the function needs so it'll hit the guard page before it hits memory after it, thus reliably detecting stack overflow. So basically what I'm confused about here is whether you're encountering a segfault which is simply a stack overflow that isn't being detected as such due to the lack of stack probes (#16012) or whether this is a genuinely different issue involving incorrect codegen for functions over a certain stack size. |
It might be both. IIRC the last explanation we had attempted to come to is that the debug version wasn't segfaulting (and properly printing the values) because it wasn't inlining the array creation code function, which then reduced the total stack size required for main. However, @eddyb (and I assume the github user @emk (with same irc handle)) did confirm bad codegen. For example, in many cases it generates a positive stack pointer offset:
which then cause bad accesses presumably. However it wasn't clear why certain values of SIZE (i.e., on my machine 1024) run fine, but when the local variables are switched around, etc., segfaults only occur in release, etc. Again lots of strangeness going on. |
Oh, and I should add that there shouldn't be any problems with a 1GB stack on linux (once ulimit is set appropriately). This C program runs fine once ulimit is set. #include<stdio.h>
int main () {
int arr[1073741824] = {};
arr[0x200000] = 0xdeadbeef;
printf("0x%x\n", arr[0x200000]);
} (EDIT: when you compile with GCC :P) |
@m4b: I'm on IRC under emk- (with minus), and here with w. @emk memory is coherent and in a good shape ;). Some more insight on this for those interested: ====
1:30c # 1GB - negative offset
movq %rsi, -1073741784(%rbp)
2:31c # 2GB - negative offset
movq %rsi, -2147483608(%rbp)
3:31c # 3GB - positive offset (wrong side of stack beginning)
movq %rsi, 1073741864(%rbp)
==== Clang suffers from the same issue (generating positive offsets over 2GB of alloca in function) diff of clang-generated asm from C code with 1GB vs 3GB array on stack. |
I can't find a LLVM bug report matching this, although who knows how, if ever, this was reported. |
I'm running For me, this works: For me, this segfaults: `let input_bytes = [0u8;2 * 1024 * 1024];
It's not possible to catch this with Behaviour above is is the same with |
@nathanaeljones as the name suggests, Also, your issue is probably closer to being this one: #36001 |
@Aatch Don't think this is related to performance issues of stack arrays. |
I believe this was fixed with #16012, so closing. |
Note, first make sure to set
ulimit -s unlimited
before running the program below.Something like the following has problems with bad ASM stack offsets/accesses being generated due to 32-bit overflow.
Looks like this is something known in LLVM: https://groups.google.com/forum/#!topic/llvm-dev/g4sF46a47_w
This also only seems to cause segfaults in
--release
modeNote however, it's not entirely clear how to easily get a directly heap allocated, large fixed size array without resorting to unsafe, box syntax, or using the vec hack.
I suspect this will come up often as a result, since many people and beginners will attempt to stack allocate a large object only to have it segfault.
Various values can be tweaked to make it not segfault in release or debug, in an entirely unintuitive way, which lends the language a less user friendly feeling, along with violating the principle of least surprise in many cases, imho.
The text was updated successfully, but these errors were encountered: