even when I give the string size as 1, whatever string I enter gets entirely printed, why does this happen? I thought that the surplus elements would be ignored.
#include <stdio.h>
#include <stdlib.h>
#include<string.h>
int main ()
{
int i;
char * buffer;
printf ("How long do you want the string? ");
scanf ("%d", &i);
buffer = (char*) malloc (i+1);
if (buffer==NULL) exit (1);
printf("\n enter string");
scanf("%s",buffer);
printf ("\n string: %s\n",buffer);
free (buffer);
return 0;
}
To add to the excellent answers already given, the following is a practical example of a buffer overrun in in practice:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
int i;
char * buffer;
static char * oops = "oops!";
printf ("How long do you want the string? ");
scanf ("%d", &i);
buffer = (char*) malloc (i+1);
if (buffer==NULL) exit (1);
char * other_variable = (char*) malloc (strlen(oops) + 1);
printf ("\n memory location of buffer: %u\n", (unsigned int)&buffer[0]);
printf ("\n memory location of other variable: %u\n", (unsigned int)&other_variable[0]);
printf("\n enter string without spaces longer than %u characters>", (unsigned int)&other_variable[0] - (unsigned int)&buffer[0]);
scanf("%s",buffer);
memcpy(other_variable, oops, strlen(oops) + 1);
printf ("\n string: %s\n",buffer);
free (buffer);
return 0;
}
Example output:
How long do you want the string? 1
memory location of buffer: 3671064576
memory location of other variable: 3671064592
enter string without spaces longer than 16 characters>aaaaaaaaaaaaaaaaaaaaaaaaaaa
string: aaaaaaaaaaaaaaaaoops!
Conversely, the following example shows how a buffer overrun in the buffer can overwrite another important variable:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
int i;
char * buffer;
static char * important_command = "Important Command!";
printf ("How long do you want the string? ");
scanf ("%d", &i);
buffer = (char*) malloc (i+1);
if (buffer==NULL) exit (1);
char * other_variable = (char*) malloc (strlen(important_command) + 1);
memcpy(other_variable, important_command, strlen(important_command) + 1);
printf ("\n memory location of buffer: %u\n", (unsigned int)&buffer[0]);
printf ("\n memory location of other variable: %u\n", (unsigned int)&other_variable[0]);
printf("\n enter string without spaces longer than %u characters>", (unsigned int)&other_variable[0] - (unsigned int)&buffer[0]);
scanf("%s",buffer);
printf ("\n Contents of buffer: %s\n", buffer);
printf ("\n Contents of other variable (should be '%s'): %s\n",important_command, other_variable);
free (buffer);
return 0;
}
Example output:
How long do you want the string? 1
memory location of buffer: 1766850560
memory location of other variable: 1766850576
enter string without spaces longer than 16 characters>aaaaaaaaaaaaaaaaaaaaaa
Contents of buffer: aaaaaaaaaaaaaaaaaaaaaa
Contents of other variable (should be 'Important Command!'): aaaaaa
Now you can imagine that if that was a SQL command or something similar then this could be catastrophic to the operation of the application and would cause a major security risk.
The real answer to your question is: you should use the fgets()
function instead (and then parse it with sscanf()
if you need to).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ()
{
#define num_length 10
int i;
char * buffer;
buffer = (char*) malloc (num_length);
printf ("How long do you want the string? ");
fgets(buffer, num_length, stdin);
sscanf (buffer, "%d", &i);
free(buffer);
buffer = (char*) malloc (i+1);
if (buffer==NULL) exit (1);
printf("\n enter string less than %i characters>", i);
fgets(buffer, i+1, stdin);
printf ("\n string: %s\n",buffer);
free (buffer);
return 0;
}