This question already has answers here:
Array index out of bound behavior
(10 answers)
Why out of bound array accessible in C? [duplicate]
(3 answers)
Closed 9 years ago.
int main()
{
int a[2] = {1,2};
a[2] = 3;
printf("\n\n%d %d %d\n\n",a[0],a[1],a[2]);
return 0;
}
I get output as 1 2 3
Why no error is thrown at run time or compile time?
Have you heard about all the security problems caused by buffer overruns? They exist because C doesn't have any automatic array bounds checking. It's the programmer's responsibility to ensure that they don't address outside the array limit, the compiler doesn't check for it.
Just make sure you don't address anything out of the boundary since, C doesn't check array bounds.
int a[2] is allocated as an automatic variable on the stack. In Windows the stack is initially allocated as 1MB for a process. So, what has really happened is that when the code assigned a[2] = 3; an area outside of the stack frame for main() was updated.
More often than not this causes a problem, such as a segmentation fault, but in simple programs stuff like this sometimes still works.
An interesting test would be to call a sub-routine that also defines and sets some automatic variables and after it returns print the value of a[2] to see if it got overwritten by the stack frame for the sub-routine? If you do this, please let me know the results!
Related
This question already has answers here:
Stack smashing detected
(10 answers)
Closed 7 months ago.
int main(){
char x[] = "123";
srand(time(NULL));
scanf("%s", x);
printf("%s\n", x);
// run();
return 0;
}
But when I make x a global variable it works just fine. Is there any reason behind this?
If you're entering in more than 3 characters, you're writing past the end of the array. Doing so triggers undefined behavior.
With undefined behavior, there are no guarantees regarding what your program will do. It may crash, it may output strange results, or it may appear to work properly.
As for what's happening in practice, local variables reside on the stack. So if you write past the bounds of a stack variable, you could end up overwriting the function's return pointer to its caller or over special sentinel values that are designed to detect such a case.
Global variables on the other hand reside in a data section, not the stack, so it's unlikely that stack objects could be overwritten. It's still possible to overwrite other objects however.
This question already has answers here:
No out of bounds error
(7 answers)
How dangerous is it to access an array out of bounds?
(12 answers)
Closed 3 years ago.
In C, I noticed I can write to static array off-limits, for example:
static char a[10] = {0};
for (int i=0; i<20; i++) {
a[i] = 'a'; // Should fail when i > 9
}
I expected to get segmentation fault but it executes just fine.
If static arrays were allocated on the stack, it would make sense, but they're not, so why is that so?
Note: static int arrays behave similarly. Didn't check other types.
Thanks.
Edit: This is not a duplicate since the other questions were not about static arrays. Unlike "regular" arrays, static arrays are allocated in BSS. The behavior might be different, which is why I'm asking separately.
You will only get a segmentation fault when you actually attempt to write to memory
that is an illegal address. Your example code writes beyond what you allocated for the array, but that isn't an address beyond what the OS determines is legal for you to use.
Even if you do not get a segmentation fault, your example code could corrupt other data structures in your code and cause major faulty behavior of a program, and possibly even worse, it can cause intermittent and difficult to debug faulty behavior.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 4 years ago.
I was trying to access a variable from the previous stack and it gave me the following error in Linux:
.... terminated by signal SIGSEGV (Address boundary error
However in CS61C lecture from 2014, the output was coming as:
3
Something Random
How did it even work in that machine vs my Linux?
Why did it print 3 the first time but not the second time? If printf didn't use that slot for something else, that behavior should have happened the second time as well no?
Below is the code:
#include<stdio.h>
int *ptr() {
int y;
y = 3;
return &y;
}
main() {
int *stackAddr, content;
stackAddr = ptr();
content = *stackAddr;
printf("%d", content);
content = *stackAddr;
printf("%d", content);
}
The lecture notes are more about a study of the behaviour of a particular compiler rather than anything else: The assertion in your picture that "Pointers in C allow access to deallocated memory" is not true from a language perspective; the behaviour is merely undefined by the C standard.
Your best bet here therefore is to inspect the generated assembly; this is unanswerable at the language level as the language does not define the behaviour.
Your assumption is not exactly true:
If printf didn't use that slot for something else, that behavior should have happened the second time as well no?
No.
For the first call the illegal memory access is done before calling printf as the parameter must be evaluated before you can call the function. For the second call the expression is evaluated again and anything could have happened in the meantime.
That's what happens if you invoke UB.
This question already has answers here:
Why don't I get a segmentation fault when I write beyond the end of an array?
(4 answers)
Closed 6 years ago.
I have declare an int array of just three elements but I notice that I can access to array indexes bigger
int x[3];
int length = sizeof(x)/sizeof(x[0]);
printf("\n the length defined is %i but I can still setting and getting other indexes")
One of the things that makes C fast is that it doesn't do any type of bounds checking on arrays. It expects programmers to know what they're doing to stay within the proper bounds.
Failure to do so means accessing a portion of memory outside the bounds of the array and leads to undefined behavior.
When accessing an index bigger than an array length, what you are actually doing is to "invade" a memory area that you are not supposed to access. This can lead to unexpected behavior of your application or a crash.
This question already has answers here:
I want this to crash, but it doesn't
(4 answers)
Closed 7 years ago.
#include<stdio.h>
#include<stdlib.h>
int main()
{
int *a[10];
a[2] = (int*)malloc(sizeof(int));
a[2][3]=4;
printf("%d", a[2][3]);
return 0;
}
I have given only the memory equivalent of a single int to the pointer variable. How is that I am able to access an element at index 3 for that pointer of a single int?
That's because nothing is preventing you accessing arrays out of bound and this invokes undefined behavior. Any expected or unexpected behavior of program can be seen.
You can try but the behaviour of your program will be undefined.
C does not perform that kind of checking at runtime.
You're accessing some randomly set RAM element. This is a common C programming mistake and is one of the reason for many security flaws.
The Heartbleed bug would be a nice example, where people were able to read a good portion of the server RAM, by accessing elements outside of the array structure.