Strcpy a bigger string to a smaller array of char - c

Why when I do this:
char teststrcpy[5];
strcpy(teststrcpy,"thisisahugestring");
I get this message in run time:
Abort trap: 6
Shouldn't it just overwrite what is in the right of the memory of teststrcpy? If not, what does Abort trap means?
I'm using the GCC compiler under MAC OSX
As a note, and in answer to some comments, I am doing this for playing around C, I'm not going to try to do this in production. Don't you worry folkz! :)
Thanks

I don't own one, but I've read that Mac OS treats overflow differently, it won't allow you to overwrite memory incertian instances. strcpy() being one of them
On Linux machine, this code successfully overwrite next stack, but prevented on mac os (Abort trap) due to a stack canary.
You might be able to get around that with the gcc option -fno-stack-protector
Ok, since you're seeing an abort from __strcpy_chk that would mean it's specifically checking strcpy (and probably friends). So in theory you could do the following*:
char teststrcpy[5];
gets(teststrcpy);
Then enter your really long string and it should behave baddly as you wish.
*I am only advising gets in this specific instance in an attempt to get around the OS's protection mechanisms that are in place. Under NO other instances would I suggest anyone use the code. gets is not safe.

Shouldn't it just overwrite what is in the right of the memory of teststrcpy?
Not necessarily, it's undefined behaviour to write outside the allocated memory. In your case, something detected the out-of-bounds write and aborted the programme.

In C there is nobody who tells you that "buffer is too small" if you insist on copying too many characters to a buffer that is too small you will go into undefined behavior terrority

If you would LIKE to overwrite what's after 5th char of teststrcpy, you are a scary man. You can copy a string of size 4 to your teststrcpy (fifth char SHOLULD be reserved for NULL).

Most likely your compiler is using a canary for buffer overflow protection and, thus, raising this exception when there is an overflow, preventing you from writing outside the buffer.
See http://en.wikipedia.org/wiki/Buffer_overflow_protection#Canaries

Related

Why is removal of sprintf() from the following code causing segmentation fault?How to deal with it?

I intend to remove sprintf() from my code because its not needed any more in my code .But when I do that,it is causes a segmentation fault,whereas it works fine when sprintf() is there.Please tell me the reason for this and how to resolve this problem.
unsigned char status_str[40]={0};
sprintf(status_str,"found HTTP:%dth time\n",(count+1));
First, using sprintf(3) is deprecated (or at least not recommended, see the BUGS section of the linked man page), it is a dangerous function (because of possible buffer overflow). You should use snprintf (which is standard since C99, i.e. since previous century) and code instead
snprintf (status_str, sizeof(status_str),
"found HTTP:%dth time\n", (count+1));
The reason why snprintf is preferable to sprintf is that even if the output overflows the buffer, snprintf won't overflow the given size, while sprintf, not knowing any size limit, will overflow.
Then, if your sprintf avoids some segmentation fault (assuming it does not overflow status_str), you've been hurt by some undefined behavior elsewhere in your program.
I would imagine that doing the sprintf fills perhaps [the stack location of] some uninitialized value with some stuff which happens to make it work later.
I suggest compiling with -Wall -Wextra -g (improving the code till you get no warning) and use the gdb debugger (its watch command is helpful). You could also use valgrind to hunt memory leaks (and some uninitialized access).
If you want some more help please show some more source code.
With a GNU libc, you could also use asprintf which allocates and fills some heap-malloc-ated zone. This function is GNU specific (and you should ensure the pointer is free-d later).
Where exactly does it segfault? If you really just remove it and the code doesn't reference status_str anymore then it could indicate a stack corruption. The error might occur somewhere earlier and it works randomly, but when the stack layout changes, an seemingly unrelated part of the code can break for no obvious reason.
For example: If an earlier code overwrites the stack with some values, and these values are reaching into status_str, no harm is done, but when that is gone, something else is overwritten and this can cause the segfault.
That's just a guess though. So you should check the code that is called before that particular function is called.
To clarify: It can be any memory, not neccessarily the stack, depends on where this is defined.

Array is larger than allocated?

I have an array that's declared as char buff[8]. That should only be 8 bytes, but looking as the assembly and testing the code, I get a segmentation fault when I input something larger than 32 characters into that buff, whereas I would expect it to be for larger than 8 characters. Why is this?
What you're saying is not a contradiction:
You have space for 8 characters.
You get an error when you input more than 32 characters.
So what?
The point is that nobody told you that you would be guaranteed to get an error if you input more than 8 characters. That's simply undefined behaviour, and anything can (and will) happen.
You absolutely mustn't think that the absence of obvious misbehaviour is proof of the correctness of your code. Code correctness can only be verified by checking the code against the rules of the language (though some automated tools such as valgrind are an immense help).
Writing beyond the end of the array is undefined behavior. Undefined behavior means nothing (including a segmentation fault) is guaranteed.
In other words, it might do anything. More practical, it's likely the write didn't touch anything protected, so from the point of view of the OS everything is still OK until 32.
This raises an interesting point. What is "totally wrong" from the point of view of C might be OK with the OS. The OS only cares about what pages you access:
Is the address mapped for your process ?
Does your process have the rights ?
You shouldn't count on the OS slapping you if anything goes wrong. A useful tool for this (slapping) is valgrind, if you are using Unix. It will warn you if your process is doing nasty things, even if those nasty things are technically OK with the OS.
C arrays have no bound checking.
As other said, you are hitting undefined behavior; until you stay inside the bounds of the array, everything works fine. If you cheat, as far as the standard is concerned, anything can happen, including your program seeming to work right as well as the explosion of the Sun.
What happens in practice is that with stack-allocated variables you are likely to overwrite other variables on the stack, getting "impossible" bugs, or, if you hit a canary value put by the compiler, it may detect the buffer overflow on return from the function. For variables allocated in the so-called heap, the heap allocator may have given some more room than requested, so the mistake may be less easy to spot, although you may easily mess up the internal structures of the heap.
In both cases you can also hit a protected memory page, which will result in your program being terminated forcibly (for the stack this happens less often because usually you have to overwrite the entire stack to get to a protected page).
Your declaration char buff[8] sounds like a stack allocated variable, although it could be heap allocated if part of a struct. Accessing out of bounds of an array is undefined behaviour and is known as a buffer overrun. Buffer overruns on stack allocated memory may corrupt the current stack frame and possibly other stack frames in the call stack. With undefined behaviour, anything could happen, including no apparent error. You would not expect a seg fault immediately because the stack is typically when the thread starts.
For heap allocated memory, memory managers typically allocate large blocks of memory and then sub-allocate from those larger blocks. That is why you often don't get a seg fault when you access beyond the end of a block of memory.
It is undefined behaviour to access beyond the end of a memory block. And it is perfectly valid, according to the standard, for such out of bounds accesses to result in seg faults or indeed an apparently successful read or write. I say apparently successful because if you are writing then you will quite possibly produce a heap corruption by writing out of bounds.
Unless you are not telling us something you answered your owflown question.
declaring
char buff[8] ;
means that the compiler grabs 8 bytes of memory. If you try and stuff 32 char's into it you should get a seg fault, that's called a buffer overflow.
Each char is a byte ( unless you are doing unicode in which it is a word ) so you are trying to put 4x the number of chars that will fit in your buffer.
Is this your first time coding in C ?

Not getting a segmentation fault when expecting it

I'm toying with buffer overflows, but I'm confused by what I'm finding when running the following simple C program on Mac OS.
#include <stdio.h>
int main(void) {
char buf[2];
scanf("%s", buf);
printf("%s\n", buf);
}
By setting the length of buf to 2 bytes, I expected to cause a segmentation fault when entering the string "CCC", but that doesn't happen. Only when entering a string 24 characters in length do I incur a segmentation fault.
What's going on? Is it something to do with character encoding?
Thanks.
The behavior of your program is undefined as soon as you overflow the buffer. Anything can happen. You can't predict it.
There might or might not be some padding bytes after your buffer that happen to be unimportant to your code execution. You can't rely on that. A different compiler, compiling in 32bit vs 64bit, debug settings... all that could alter your code execution after that overflow.
Because buf is on the stack. When you start overwriting it, you start overwriting the stack which belongs to the program which the OS won't catch depending on what else is allocated there (e.g. spill slots for registers created by the compiler). Only once you cross the allocated stack boundary the OS will have a chance to raise a segfault.
I guess it's related to the memory layout. If what you are overwriting is accessible to your process (a page mapped writable) the OS doesn't have a chance to see you're doing something "wrong".
Indeed, when doing something like this, from the eyes of a C programmer "that's totally wrong!". But in the eyes of the OS "Okay, he's writing stuff to some page. Is the page mapped with the adequate permissions ? If it is, OKAY".
There is no guarantee that you will get segmentation fault at all. There is more data after char buf[2] overwriting it may or may not cause segmentation fault.
buf is allocated on the stack, you're just overwriting an area that's not used there is a good chance that nobody will complain about it. On some platforms your code will accept whole paragraphs.

Writing more characters than malloced. Why does it not fail?

Why does the following work and not throw some kind of segmentation fault?
char *path = "/usr/bin/";
char *random = "012";
// path + random + \0
// so its malloc(13), but I get 16 bytes due to memory alignment (im on 32bit)
newPath = (char *) malloc(strlen(path) + strlen(random) + 1);
strcat(newPath, path);
strcat(newPath, "random");
// newPath is now: "/usr/bin/012\0" which makes 13 characters.
However, if I add
strcat(newPath, "RANDOMBUNNIES");
shouldn't this call fail, because strcat uses more memory than allocated? Consequently, shouldn't
free(newPath)
also fail because it tries to free 16 bytes but I used 26 bytes ("/usr/bin/012RANDOMBUNNIES\0")?
Thank you so much in advance!
Most often this kind of overrun problems doesn't make your program explode in a cloud of smoke and the smell of burnt sulphur. It's more subtle: the variable that is allocated after the overrun variable will be altered, causing unexplainable and seemingly random behavior of the program later on.
The whole program snippet is wrong. You are assuming that malloc() returns something that has at least the first byte set to 0. This is not generally the case, so even your "safe" strcat() is wrong.
But otherwise, as others have said, undefined behavior doesn't mean your program will crash. It only means it can do anything (including crashing, but also not crashing, if you are unlucky).
(Also, you shouldn't cast the return value of malloc().)
Writing more characters than malloced is an Undefined Behavior.
Undefined Behavior means anything can happen and the behavior cannot be explained.
Segmentation fault generally occurs because of accessing the invalid memory section. Here it won't give error(Segmentation fault) because you can still access memory. However you are overwriting other memory locations which is undefined behavior, your code runs fine.
It will fail and not fail at random, depending on the availability of the memory just after the malloc'd memory.
Also when you want to concat random you shouldn't be putting in quotes. that should be
strcat(newPath, random);
Many C library functions do not check whether they overrun. Its up to the programmer to manage the memory allocated. You may just be writing over another variable in memory, with unpredictable effects for the operation of your program. C is designed for efficiency not for pointing out errors in programming.
You have luck with this call. You don't get a segfault because your calls presumably stay in a allocated part of the address space. This is undefined behaviour. The last chars of what has been written are not guaranteed to not be overwritten. This calls may also fail.
Buffer overruns aren't guaranteed to cause a segfault. The behavior is simply undefined. You may get away with writing to memory that's not yours one time, cause a crash another time, and silently overwrite something completely unrelated a third time. Which one of these happens depends on the OS (and OS version), the hardware, the compiler (and compiler flags), and pretty much everything else that is running on your system.
This is what makes buffer overruns such nasty sources of bugs: Often, the apparent symptom shows in production, but not when run through a debugger; and the symptoms usually don't show in the part of the program where they originate. And of course, they are a welcome vulnerability to inject your own code.
Operating systems allocate at a certain granularity which is on my system a page-size of 4kb (which is typical on 32bit machines), whether a malloc() always takes a fresh page from the OS depends on your C runtime library.

Checking if stack allocation fails?

Is there a way to correct failed static allocation or program just fails with Segmentation or Bus Fault when run?
Post was inspired by how C99 allows crazy stuff like char text[n];
EDIT: Thanks. I now understand the part in bold is not a static alloc. So just to check, if something like char text[1234]; fails would the possible recovery strategies be the same?
char text[n] allocates a variable-size array on the stack. It simply involves incrementing the stack pointer by n.
There is not much a userspace process can do if a stack overflow occurs - it's up to the operating system to either send a signal to the process and terminate it or resize the stack.
You can probably catch the signal(s) but there's not much else you can do. Of course, checking n before using it to make sure it has a sensible value would solve this instantly.
Never check for an error condition you don't know how to handle.
Seriously, what are you planning on doing? There is only a small subset of function you are allowed to call from a signal handler (see man 7 signal), and printf and longjmp (longjmp is the only way I can think of to recover from such a problem) are not one of them. If you are going to the trouble to re-exec the process, you might as well have a nanny to do that job and avoid the mess.
Note according to man alloca you don't actually get told that the "allocation" fails, you just get a SIGSEGV when you try to access the bad memory, and of course that might not happen in the text[] array at all, or perhaps not even in the function that allocates text[] at all.
While the above two paragraphs are based on Linux, the overarching theory is true for all platforms.
Use malloc and have clean handling. Be sane.
[EDIT]
Actually there is one way to try and do this, and that is by computing the start of the stack (recording stack in main) and stack limit (hoping the OS doesn't run out of pages). Then before you do the large stack allocation you can compute how close you are to the end. Give yourself a generous wiggle-room and fail before you allocate.
This is a stack allocation rather than static. The failure mode is stack overflow. The most rational policy for stack overflow is to regard it as terminal.
Design your code so that it won't overflow the stack rather than trying to make it resilient to stack overflow.

Resources