Reputation: 87
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;
}
Upvotes: 0
Views: 667
Reputation: 3562
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;
}
Upvotes: 0
Reputation: 52530
Because you have a buffer overflow, which invokes undefined behaviour. Anything can happen. One of the things that can happen is that the string is printed completely. Other things that can happen is that your program crashes, or that a hacker attacking a user's computer uses this undefined behaviour to break in.
That's why beginners would comment on a buffer overflow "if you are unlucky, your program crashes" and more experienced programmers say "if you are lucky, your program crashes". You were not lucky.
Upvotes: 4
Reputation: 100612
C doesn't perform bounds checking. Writing beyond the end of an array simply produces undefined behaviour. In your empirical test on one particular implementation of the C runtime, your length of string produces the same thing as correct behaviour. It's not guaranteed to.
(in practise, on most modern architectures: if you access an address you definitely don't have the right to, that'll raise an exception; however there's only a broad resolution for such checks and malloc
attempts tightly to pack allocated space so as to minimise wasted RAM; given that there is no bounds check when you do the array access all that's happening is that you're storing and subsequently retrieving bytes from memory your process owns; but it's not guaranteed that you own it in the general case and, even if you do on your particular architecture, you may well be overwriting something else; hence what you're doing is relying on undefined behaviour)
Upvotes: 2