tags:

views:

70

answers:

2

Why does scanf give a max value in case of "int" but crash the program in case of "char" when the limit is exceeded?

#include<stdio.h>
main(){
int a;
char ch[10];
scanf("%d",&a);
printf("%d",a);
scanf("%s",ch);
printf("%s",ch);
}
+1  A: 

Because you're not reading a character, you're reading a string. And scanf does not "know" that you only have space for 10 characters (including the null). This is the joy of C programming.

You can protect yourself in this case by adding a width modifier:

%9s
djna
+2  A: 

It crashes your program in this case because scanf() has an inherently unsafe interface for strings. It has no way of knowing that your parameter ch is an array large enough to hold a 9-character string plus its terminating nul. As a result, it is perfectly happy to keep reading characters from stdin and storing them in memory well past the end of the array.

If your program crashes, you are actually lucky. In the worst case, the attacker has used a carefully crafted string to manipulate the content of the stack in such a way that he has gained control of your computer. This is an example of a buffer overflow attack. It sounds unlikely, but it has been documented to occur on a large number of occasions.

Used for only numbers, scanf is generally safe enough, but it is not very good at handling errors in the input. As a result, it is usually a good idea to use something like fgets() to read the input (it has a buffer length parameter to control overflow) and sscanf() to parse from that buffer, testing its return values for sanity as you go.

Edit: As the comment from R points out, I overstated the dangers inherent to the scanf interface. With care to correctly use the field width specifier on all strings, scanf becomes safer. But then you take responsibility for guaranteeing that the specified width does fit within the buffer. For the example, you should write scanf("%9s",ch); because your buffer was declared to be ten bytes long and you need room for the terminating nul.

Note that you should also be testing the return value from scanf(). It returns the number of fields it successfully matched, or EOF if an I/O error occurred. It might return 0 if the user entered "abc" when it expected a number, for instance.

RBerteig
The interface is safe if you use it correctly: `%9s`.
R..
thanks this helped
mielacademy
@R., well, true. Note that it is rather inconvenient to keep the size of the buffer in sync with the format specifier. That is one reason to strongly recommend using `fgets()` followed by a more robust parser instead.
RBerteig