-2
#include<stdio.h>
int main()
{
char str[10];
scanf("%[^\n]", str);
printf("%s\n", str);
}

when this is compile and input is given as "subhash das india". Output is same as subhash das india. I want to know how the string is stored in memory as str size is 10 and size of input given is greater than 10.

zishe
  • 10,665
  • 12
  • 64
  • 103
vishal kumar
  • 43
  • 1
  • 9

3 Answers3

0

printf will continue to print until it finds the null (terminating character):\0 thus although only 10 bytes are set aside the text will still be put in the array as str is just a pointer to an array.

james
  • 1,035
  • 2
  • 14
  • 33
0

The array str takes 10 bytes from stack of the application.

Some compilers calculate the required stack size by simply sum the number of bytes of all variables, arrays and structures located on stack in all functions plus the number of bytes all function arguments and the function calls would need. But this stack size calculation is definitely always wrong as not all functions are called in a sequence.

Therefore many compilers often define a fixed stack size which is allocated on start of the application before main is called. The stack size can be controlled by a developer, for example when an application needs more than applications usually need because of lots of recursive function calls.

For example, take a look on the Visual Studio page about /F (Set Stack Size). The default stack size for C/C++ applications compiled with Visual C/C++ have 1 MB of stack.

Therefore it is no problem on your simple code that a string with more than 10 bytes is copied on stack to the location on which str points. The string from scanf is terminated with a null byte. printf simply outputs bytes until a null byte is found.

But if you would modify your code by adding a function which contains for example also an array located on stack which is additionally also initialized with something, and this function is called between scanf and printf, you would see a different string on output as used on input.

scanf and printf should be both not used anymore because of no check on array sizes. The C/C++ libraries and the various frameworks/libraries offer more secure functions which check the sizes of the string arrays.

Mofi
  • 46,139
  • 17
  • 80
  • 143
  • Unfortunately, you don't really know about the dangers of the code in the question. The stuff about the stack size is dangerously misleading wrong. – cmaster - reinstate monica May 24 '14 at 14:35
  • I know the danger of such code very well. Such code makes it possible to manipulate the stack of the application and therefore makes it possible that a completely different code is executed than what was compiled. scanf, gets and some other functions from C library are unsafe and as I wrote, should not be used anymore as there are also safe functions replacing them. But the questioner wanted to know why this little code works at all. It works by chance and I wrote the reason in case of the questioner used Visual C/C++ for compilation. Such a code is definitely a NO GO - NEVER EVER. – Mofi May 24 '14 at 15:05
  • Then what are you talking about the stack size? It's completely irrelevant: the stack grows down, while the buffer overflow goes upwards. If you overflow too much, you hit the top of the stack (after overwriting all local data of all calling functions), but how much you can overflow before segfaulting has nothing to do with the allowable stack size, it only has to do with the current, effective stack size. – cmaster - reinstate monica May 24 '14 at 15:25
  • The majority of the C/C++ programmers do not know anything about stack management from my experience. They think, the definition of an array of 10 bytes in size results in reserving memory of exactly 10 bytes on stack which of course is not true, especially with taking alignment also into consideration. The questioner wanted to know why the application does not immediately crash when a string with more than 9 bytes is entered. And the reason is that the application allocated in total more than the 10 bytes for the entire application's stack because of a default stack size. – Mofi May 24 '14 at 17:08
  • is it safe to use fgets? if yes check this simple code on linux plateform. I am using Fedora. #include int main() { char c[10]; fgets(c, 50, stdin); printf("%s\n", c); } in this output is string more than size of array. Maximum upto 20. after having input of 21 it give cordump. can u explain me. – vishal kumar May 24 '14 at 17:29
  • With `char c[10]` it would be safe to use `fgets(c,sizeof(c)/sizeof(char),stdin)` which results in reading a maximum of 9 characters from stdin. Using in `fgets` a value for the array size greater than the array is, results again in a buffer overflow. – Mofi May 24 '14 at 17:52
0

The first ten characters are stored in the array, the rest in the bytes right after the array in memory. You don't know what was supposed to be stored in these bytes, nevertheless you overwrite them with the string "s india". This is bad. Even though it might work in this case, it is not even likely that it will work with a different compiler / on a different system / when you you run the program again.

printf() does not care what you have overwritten, it will only search the string for the terminating null byte, which happens to come somewhere after the end of the array. The unexpected behavior is not likely to take effect until you return from your function (main() in this case), which may segfault, or use some other variables declared in main() which happen to have been overwritten by scanf().

Note, that the behavior of your program is entirely undefined. It is allowed to format your harddrive. It is allowed to save a backup of your computer to the NSA. It is allowed to download a nifty little program that will automatically redirect your browser the next time you try to do online banking. These are real dangers, code like the one you've given is at the heart of the most easily exploitable security holes.

If you want to be safe, use the POSIX-2008 functions: getline() to read entire lines and asprintf() to replace use of sprintf() and strcat(). The GNU implementation of the standard C library also allows you to use the format "%as" with scanf() to allocate enough memory for the string that is to be read, but that is not a part of a standard.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
  • can u give me example. – vishal kumar May 24 '14 at 16:25
  • is it safe to use fgets? if yes check this simple code on linux plateform. I am using Fedora. #include int main() { char c[10]; fgets(c, 50, stdin); printf("%s\n", c); } in this output is string more than size of array. Maximum upto 20. after having input of 21 it give cordump. can u explain me. – vishal kumar May 24 '14 at 17:12
  • `fgets()` is safe in that it does not overflow the buffer if you call it correctly. But it is nevertheless tricky to use correctly: You still need to handle the case that the string did not fit into your buffer *and is truncated*. Just going on to work with a truncated string is definitely a bug. Not as dangerous a security hole as overflowing a buffer, but definitely annoying to your users, and definitely reducing the flexibility of your software. – cmaster - reinstate monica May 25 '14 at 14:56