I was having a very weird segfault that I eventually fixed today. It seems the problem was I was allocating a very large array on stack and that was causing the problem.
My question is, do you always get a SEGV signal on stack overflow? Is there any special signal that could alert there is a stack overflow problem?
I'm using g++ along with gdb.
The "signal" in the sense of Unix signals is apparently SEGV. :) If you mean signal like using a diagnostic tool that will tell you when something bad is happening, you could try valgrind, but really, your system just told you. And knowing at compile time whether the stack will be overflowed is not possible, partly because the stack size limit is a runtime parameter, and besides I imagine if you knew what it would be a priori, you'd still be stuck with something like the Halting Problem.
Related
I am making a library that have too much code to give it here.
My problem is a segmentation fault, that Valgrind analyse as:
Jump to the invalid address stated on the next line
at 0x72612F656D6F682F: ???
at [...] (stack call)
Thanks to this question, I guess it is because I have a stack corruption somewhere.
My question is: how to find it?
I tried using GDB, but the segmentation fault appears to not be at the same place. GDB tell me it is on the first line of a function while Valgrind tell it is the call of this function that make a segmentation fault.
If the problem is repeatable, you can use technique similar to this answer to set a watchpoint on the location of return address, and have GDB stop on the instruction immediately following the one that corrupts it.
Since this is from years ago, you've probably figured out your bug. But for anyone who might stumble upon this, I would strongly encourage you to look into the "sanitizers".
If you're running Memcheck, you can probably run AddressSanitizer, which exists in both clang and gcc. AddressSanitizer can often detect stack corruption issues better than Memcheck. (Besides stack corruption, AddressSanitizer can detect many different types of addressing bugs).
However, if you scroll back in your Memcheck log, you might see Conditional jump or move depends on uninitialised value(s), in which case you're using an uninitialized variable, which is often harder to debug. For this, you can try MemorySanitizer (currently clang and Linux only, https://clang.llvm.org/docs/MemorySanitizer.html). In particular, look at the origin tracking options. This provides better origin tracking than Memcheck for uses of uninitialized variables. Do note, however, that MemorySanitizer is not trivial to set up, as it generally requires all external libraries to be built with (MemorySanitizer) instrumentation.
So I have a person that I allowed to test out my Socket program and they got it to segfault with the message:
*** stack smashing detected ***: ./myProgram terminated
Which as I understand it, is a gcc compiler feature that detects when the stack gets unstable and kills the program. The problem is not the stack smashing, but the way that it happened. Apparently my program is vulnerable to remote code execution. He was connected via telnet.
I believe he used telnet to cause my socket program to segfault. What I don't know is how he did it and how to prevent it. My socket program is handling the buffering with a 1024 byte long char[]. And even if I tried with a 5 byte buffer and the message get's split up when it's over 5 bytes in that case.
So in summation I'm wondering if anyone knows how to "inject code" via telnet or some other method when the socket being connected to is custom written. And also how to prevent it from happening.
Edit:
Here's my source code: https://github.com/theMonster/ModularServer
In Chatroom::recievedCommand you several times allocate buffers on the stack as char tmp[1024]; and then write text into them using sprintf, with no guarantee that the data written will be less than 1024 bytes.
This is pretty much the canonical example of a buffer overrun. OWASP has a whole page explaining the dangers here, and there's also lots of existing questions about this sort of thing on Stack Overflow. A quick search turned up understanding the dangers of sprintf(…) which is probably useful as well.
The simple answer is that your program has a bug.
You cannot "inject code" into a correctly written program.
Fix the bug, and attacks will go away. Typically the bug is of the form that your program behaves correctly for only some kinds of input but not for others, presumably because you either don't check all possible return paths from functions or don't check conditions on data sizes and array lengths and things like that.
There are static and dynamic analysis tools that may be able to point you to a specific problem (such as Valgrind, ASan and UBSan), but mostly you need to approach programming with the right attitude, be methodical and pay sufficient attention to detail.
In Microsoft Visual C++ 2010 I created a program which delibrately causes a stack overflow. When I run the program using "start debugging" an error is thrown when stack overflow occurs. When I run it with "start without debugging" no error is thrown and the program just terminates silently as if it had successfully completed. Could someone explain to me what's going on? Also do any other compilers not throw errors on stack overflow?
(I thought this would be the right place to ask a question about stack overflow.)
C++ won't hold your hand as a managed enviroment does. Having a stack overflow means undefined behaviour.
A stack overflow is undefined behaviour. The compiler is well within it's rights to ignore it or cause any event to happen.
Because when your process stack overflows, it is no longer a valid process. Displaying an error message requires a stack.
Raymond Chen went over this recently.
As for why the debugger is able to throw such an exception, in that case the process is being kept around because it's attached in debugging mode to the debugger's process. Your process isn't displaying the error, the debugger is.
On Windows machines, you can catch the SEH exception which corresponds to a stack overflow. For an example, you can see boost::regex's source code (Google for BOOST_REGEX_HAS_MS_STACK_GUARD).
It might well be that the compiler optimized the intended stack overflow away. Consider the following pseudo-code example:
void RecursiveMethod(int n)
{
if (n % 1024 == 0)
print n;
// call recursively
RecursiveMethod(n + 1);
}
The method will call itself recursively and overflow the stack pretty quickly because there is no exit condition.
However, most compilers use tail recursion, a technique which will transfer the recursive function call into a loop construct.
It should be noted that with tail recursion, the above program would run in an endless loop and not exit silently.
Bart de Smet has a nice blog article where explains how this technique works in .NET:
The Case of The Failed Demo – StackOverflowException on x64
In a debug build, a number of stack checks are put in place to help you detect problems such as stack overflows, stack corruption etc. They are not present in release builds because they would affect the performance of the application. As others have pointed out, a stack overflow is undefined behaviour, so the compiler is not required to implement such stack checks at all.
When you're in a debugging environment, the runtime checks will help you detect problems that will also occur in your release build, therefore, if you fix all the problems detected in your debug build, then they should also be fixed in your release build . . . in theory. In practice, sometimes bugs that you see in your debug build are not present in your release build or vice versa.
Stack overflows shouldn't happen. Generally, stack overflows occur only by unintentional recursive function calling, or by allocating a large enough buffer on the stack. The former is obviously a bug, and the latter should use the heap instead.
In debugging mode, you want the overhead. You want it to detect if you broke your stack, overflowed your buffers, etc. This overhead is built into the debug instrumentation, and the debugger. In high level terms the debug instrumentation is extra code and data, put there to help flag errors, and the debugger is there to detect the flagged errors and notify the user (in addition to helping you debug, of course).
If you are running with the project compiled in release mode, or without a debugger attached, there is no one to hear the screaming of your program when it dies :) If a tree falls in the forest...
Depending on how you program, C++ is programming without training wheels. If you hit a wall, no one is going to be there to tell you that you screwed up. You will just crash and burn, or even worse, crash and keep running along in a very crippled state, without knowing anything is wrong. Because of this, it can be very fast. There are no extra checks or safe guards to keep it from blazing through your program with the full speed and potential of the processor (and, of course, how many extra steps you coded into your program).
I just ran into an issue where a stack overflow in a threaded c++ program on HPUX caused a SEGV_MAPERR when a local object tried to call a very simple procedure. I was puzzled for a while, but luckily I talked to someone who recognized this as a stack size issue and we were able to fix the problem by increasing the stack size available to the threads.
How can I recognize when the stack overflows? Do the symptoms differ on windows/linux/hpux?
Assuming you're not on a platform thats going to stop your app and say "stack overflow" I suspect you'll see the same behavior that you would see from any kind of buffer overflow. The stack is just another preallocated chunk of memory for your program, and if you go outside those bounds... well good luck! Who knows what you'll stomp on!
You could write over the temperature readout from the CPU, it could be the email you're typing to Larry, it could be the bit saying that the kernel is locked, causing a fun deadlock condition! Who knows.
As for C++, there's nothing saying how the stack should be laid out in relation to other things in memory or that this thing even needs to be a stack!
How can I recognize when the stack overflows?
If you know the stack size, where the stack starts and the direction it grows in memory, you can simply check the address of the stack pointer and see if it past the end of the stack. C++ does not allow direct access to the stack pointer. You could easily write a small function in assembly to perform this analysis and link it into you program.
Exception code 0xC00000FD on Windows.
Usually it's easier to diagnose when you realize your SEH stops working.
Perhaps a bit off topic, but the analagous issue in Ada (running out of stack space in tasks) is a rather common "uncommon" error. Many compilers will stop the task (but not the main task) with a PROGRAM_ERROR exception.
In a way, you almost have to be able to sniff out this one. It tends to start with something like, "I moved this big array inside my task, and suddenly it quit working".
Output text to screen became mixed with lines of code from program under test. Also present were previous bash commands and other text of unidentified origin. Added to all that the program text became corrupted.
So I'm trying to debug this strange problem where a process ends without calling some destructors...
In the VS (2005) debugger, I hit 'Break all' and look around in the call stacks of the threads of the misteriously disappearing process, when I see this:
smells like SO http://img6.imageshack.us/img6/7628/95434880.jpg
This definitely looks like a SO in the making, which would explain why the process runs to its happy place without packing its suitcase first.
The problem is, the VS debugger's call stack only shows what you can see in the image.
So my question is: how can I find where the infinite recursion call starts?
I read somewhere that in Linux you can attach a callback to the SIGSEGV handler and get more info on what's going on.
Is there anything similar on Windows?
To control what Windows does in case of an access violation (SIGSEGV-equivalent), call SetErrorMode (pass it parameter 0 to force a popup in case of errors, allowing you to attach to it with a debugger.)
However, based on the stack trace you have already obtained, attaching with a debugger on fault may yield no additional information. Either your stack has been corrupted, or the depth of recursion has exceeded the maximum number of frames displayable by VS. In the latter case, you may want to decrease the default stack size of the process (use the /F switch or equivalent option in the Project properties) in order to make the problem manifest itself sooner, and make sure that VS will display all frames. You may, alternatively, want to stick a breakpoint in std::basic_filebuf<>::flush() and walk through it until the destruction phase (or disable it until just prior to the destruction phase.)
Well, you know what thread the problem is on - it might be a simple matter of tracing through it from inception to see where it goes off into the weeds.
Another option is to use one of the debuggers in the Debugging Tools for Windows package - they may be able to show more than the VS debugger (maybe), even if they are generally more complex and difficult to use (actually maybe because of that).
That does look at first glance like an infinite recursion, you could try putting a breakpoint at the line before the one that terminates the process. Does it get there ok? If it does, you've got two fairly easy ways to go.
Either you just step forward and see which destructors get called and when it gets caught up. Or you could put a printf/OutputDebugString in every relevant objects destructor (ONly ones which are globals should need this). If the message is the first thing the destructor does, then the last message you see is from the destructor which hangs things up.
On the other hand, if it doesn't get to that breakpoint I originally mentioned, then can do something similar, but it will be more annoying since the program is still "doing stuff".
I wouldn't rule out there being such a handler in Windows, but I've never heard of it.
I think the traceback that you're showing may be bogus. If you broke into the process after some kind of corruption had already occurred, then the traceback isn't necessarily valid. However, if you're lucky the bottom of the stack trace still has some clues about what's going on.
Try putting Sleep() calls into selected functions in your source that might be involved in the recursion. That should give you a better chance of breaking into the process before the stack has completely overflowed.
I agree with Dan Breslau. Your stack is bogus. may be simply because you don't have the right symbols, though.
If a program simply disappears without the WER handling kicking in, it's usually an out of memory condition. Have you gone investigated that possibility ?