I have the following code:
#include <stdio.h>
int main(void)
{
char cadena[5] = {0};
int c = 10;
printf("Escriba una cadena: ");
scanf("%s", cadena);
printf("Resultado: %s, %d", cadena, c);
return 0;
}
The problem is that when the user enters 5
or more characters, the array overflows (it exceeds the limits) and incidentally, overwrites the content of the variable c
.
Example:
If the user enters a by keyboard 12345
, the result on the screen would be:
Resultado: 12345, 0
The example shows how the variable c
loses the value it had previously. So the question is: How do I avoid this potential overflow?
To avoid overflow, we need to tell the function
scanf
how many characters to read.And this is done in the following way:
Here we tell the function
scanf
that it will only be able to read up to4
characters. If the user were to write5
or more characters, they remain in the keyboard buffer.Note: The last position of the array is for the null character.
Frequent questions:
Why can't I add in the format specifier a
5
?Let's look at the following code:
Here I indicate
scanf
that you can read up to5
characters. The problem is that we are not leaving a space for the null character, so another buffer overflow will happen .Imagine that the array and the variable
c
are in memory like this:Now, when the user enters a
Holas
, then the functionscanf
will write to the array like this:But the function
scanf
is in charge of assigning the null character to the array , therefore, it will do so at the address0x0F
, which is precisely of the variablec
:We have overwritten the content of the variable again
c
! Here it is clear to us that we must ensure thatscanf
it can only read up to4
characters so that no overflow occurs.Note: In the example above, the address
0x0E
is what it should be for the null character.What if I need to read a string with spaces?
Never use the gets function to read strings with spaces, because it is deprecated and not part of the C11 standard , this means portability is lost, as not all compilers will have support for this function.
The problem with this function is that it doesn't allow you to specify the size of the array , so it's prone to buffer overflow.
So a safe way to read strings with spaces is with the fgets function :
There is also an alternative to be able to read strings with spaces using
scanf
:[^\n]
means itscanf
will read any character (even a space) except the newline.An example of this type of attack...
Malicious users could exploit this vulnerability to change the desired behavior of the program , so you should prevent this bug from being built into the application.
I've pulled an example from this page where a buffer overflow consequence can be reflected.
This program is vulnerable to a buffer overflow attack, since if the user enters more than 16 characters, it overflows the array
password
(exceeds its limit).Take the following entries as an example:
Here the user gets root privileges even though the password is wrong and this behavior is caused by overwriting the variable
pass
, so the conditionif(pass)
would be met as itpass
would be non-zero.So this is one way someone could gain access to the entire system and steal confidential information from a company (for example).
It should also be noted that buffer overflow causes undefined behavior , this means that the program may or may not work (by having UB the behavior of the program is arbitrary, anything can happen).
In the previous example, a possible behavior of the program was presented: Grant the user root privileges even though the password is incorrect and the cause was overwriting the memory of the program, however, another behavior could have occurred, such as trying to access a memory address that was not assigned to the current process (the running program), this would cause the operating system to kill the current process, so the program would stop working.
And finally, to eliminate that possible overflow from the previous example, we simply need to specify the size of the array in the function
scanf
:With this we ensure that only 15 characters are entered! Say goodbye to this vulnerability!