#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
int value = 5;
char buffer_one[9], buffer_two[9];
strcpy(buffer_one, "one"); /* Put "one" into buffer_one. */
strcpy(buffer_two, "two"); /* Put "two" into buffer_two. */
printf("[BEFORE] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
printf("[BEFORE] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
printf("[BEFORE] value is at %p and is %d (0x%08x)\n", &value, value, value);
printf("\n[STRCPY] copying %d bytes into buffer_two\n\n", strlen(argv[1]));
strcpy(buffer_two, argv[1]); /* Copy first argument into buffer_two. */
printf("[AFTER] buffer_two is at %p and contains \'%s\'\n", buffer_two, buffer_two);
printf("[AFTER] buffer_one is at %p and contains \'%s\'\n", buffer_one, buffer_one);
printf("[AFTER] value is at %p and is %d (0x%08x)\n", &value, value, value);
}
Output 1 :-
I am giving 24 bytes of data to buffer_two
variable and it is accepting it, however i assigned only 9-bytes of memory to buffer_two
. And, why the address difference between buffer_two
and buffer_one
is 16 instead of 9.
ubuntus@ubuntus:~$ ./sample2 123456789012345678901234
[BEFORE] buffer_two is at 0x7ffe29136510 and contains 'two'
[BEFORE] buffer_one is at 0x7ffe29136500 and contains 'one'
[BEFORE] value is at 0x7ffe291364fc and is 5 (0x00000005)
[STRCPY] copying 24 bytes into buffer_two
[AFTER] buffer_two is at 0x7ffe29136510 and contains '123456789012345678901234'
[AFTER] buffer_one is at 0x7ffe29136500 and contains 'one'
[AFTER] value is at 0x7ffe291364fc and is 5 (0x00000005)
Output 2:-
ubuntus@ubuntus:~$ ./sample2 1234567890123456789012345
[BEFORE] buffer_two is at 0x7fff51549fe0 and contains 'two'
[BEFORE] buffer_one is at 0x7fff51549fd0 and contains 'one'
[BEFORE] value is at 0x7fff51549fcc and is 5 (0x00000005)
[STRCPY] copying 25 bytes into buffer_two
[AFTER] buffer_two is at 0x7fff51549fe0 and contains '1234567890123456789012345'
[AFTER] buffer_one is at 0x7fff51549fd0 and contains 'one'
[AFTER] value is at 0x7fff51549fcc and is 5 (0x00000005)
*** stack smashing detected ***: ./sample2 terminated
Aborted (core dumped)
Regarding this:
I am giving 24 bytes of data to buffer_two variable and it is accepting it
As already mentioned in the comments, this is a typical case of Undefined Behavior. C doesn't put checks on the boundaries of the array and it is left to the programmer to take care of it. If the boundary of the array is breached, anything can happen. You could accidentally write on the data of other variables or the program can crash or sometimes it may work (as it happened in your case).
When I ran your code, this was the output I got:
nandan@debian:~$ ./sample 123456789012345678901234
[BEFORE] buffer_two is at 0x7ffc2db1e19a and contains 'two'
[BEFORE] buffer_one is at 0x7ffc2db1e1a3 and contains 'one'
[BEFORE] value is at 0x7ffc2db1e1ac and is 5 (0x00000005)
[STRCPY] copying 24 bytes into buffer_two
[AFTER] buffer_two is at 0x7ffc2db1e19a and contains '1234567890123456789012345'
[AFTER] buffer_one is at 0x7ffc2db1e1a3 and contains '0123456789012345'
[AFTER] value is at 0x7ffc2db1e1ac and is 842084409 (0x32313039)
Many things can be noticed when we compare the outputs of mine and yours.
First, both of our programs didn't crash. Hurray!
Second, notice that in your output, buffer_one
was allocated the memory first and then buffer_two
was allocated (hence, buffer_two
has higher address than buffer_one
. That's obvious right? They are allocated in the order of which they are declared in the code). But, in my case, buffer_two
was allocated first and then buffer_one
was allocated (notice that, in my output, buffer_two
has lower address than buffer_one
). So, why did this happen in my case? Well, it is compiler-dependent feature. The order in which the automatic variables are allocated on the stack is entirely left to the compiler. I don't know why exactly this happened but I guess it has something to do with optimization. Here for more.
Third, since in my case buffer_two
has lower address than buffer_one
, an Undefined behavior can be noticed when copying the 24-byte string in the 9-byte buffer_two
. buffer_one
is getting overwritten!! [AFTER] buffer_one is at 0x7ffc2db1e1a3 and contains '0123456789012345'
.
Now, Regarding this:
however i assigned only 9-bytes of memory to buffer_two. And, why the address difference between buffer_two and buffer_one is 16 instead of 9.
Notice that, in my case, exact 9 bytes are allocated for buffer_one and buffer_two by my GCC.
Normally, GCC tries to keep your automatic variables aligned to 2^n bytes on the stack so as to improve the performance even though it sacrifices few bytes for it. By default n=4. So, 16 (2^4) bytes are allocated in your case for a 9-byte array and the remaining 7 bytes are padded with null characters.
You can use -mpreferred-stack-boundary
flag in GCC to change this alignment.
Read the docs or search for other questions on SO on the usage of that flag.