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);
}
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);
}
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
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.